Chapter 1. Why functional programming? Why Haskell?

Table of Contents

Have we got a deal for you!
Novelty
Power
Enjoyment
What to expect from this book
A little bit about you
What to expect from Haskell
Compared to traditional static languages
Compared to modern dynamic languages
Haskell in industry and open source
Compilation, debugging, and performance analysis
Bundled and third party libraries
A brief sketch of Haskell's history
Prehistory
Early antiquity
The modern era
Helpful resources
Reference material
Applications and libraries
The Haskell community

Have we got a deal for you!

Haskell is a deep language, and we think that learning it is a hugely rewarding experience. We will focus on three elements as we explain why we think it worthwhile. The first is novelty: we invite you to think about programming from a different and valuable perspective. The second is power: we'll show you how to create software that is short, fast, and safe. Lastly, we offer you a lot of fun: the pleasure of applying beautiful programming techniques to solve real problems.

Novelty

Haskell is most likely quite different from any language you've ever used before. Compared to the usual set of concepts in a programmer's mental toolbox, functional programming offers us a profoundly different way to think about software.

In Haskell, we de-emphasise code that modifies variables or objects. Instead, we focus on functions that take immutable values as input and produce new values as output. Given a fixed input, one of these functions will always return the same result. This is a core idea behind functional programming.

Along with not modifying data, Haskell functions don't usually talk to the external world. They don't read or write files; initiate or respond to network connections; or make robot arms move.

We abandon some ideas that might seem fundamental, such as repeating an action using a looping construct. We have other, more effective ways, to perform repetitive tasks.

Even the way in which we evaluate expressions is different in Haskell. We defer every computation until its result is actually needed: Haskell is a lazy language. This isn't just a matter of moving work around: it deeply affects how we write programs.

Power

Throughout this book, we're going to show you how Haskell's alternatives to the features of traditional languages are more powerful, more flexible, and safer. Haskell is positively crammed full of cutting edge ideas about how to create great software.

Perhaps surprisingly, when we place some restrictions on how we create code, we find that it's actually becomes easier to write and read. Every useful Haskell program talks to the outside world, and this is easy to do. But the language rigorously isolates that code: there's a strong division between code that is exposed to the outside world, and code that is not. Code that may have side effects even looks different from normal code.

Since most of our Haskell code doesn't have any dealings with the outside world, and can't modify any data, it tends to be easy to understand and to reuse. The kinds of nasty surprises in which one piece of code invisibly corrupts data used by another simply don't occur. Whatever setting we use a function in, it will behave consistently.

Code that lacks side effects is easy to test. When a function only responds to its visible inputs, we can state a property of its behaviour that should always be true, automatically test that the property holds for a huge body of random inputs, and move on. We can still unit test code that must interact with files, networks, or exotic hardware, but we get much better assurance that our software is solid.

Lazy evaluation has some spooky effects. Let's say we want to find the k least-valued elements of an unsorted list. In a traditional language, the obvious approach would be to sort the list and take the first k elements, but this approach is expensive. For efficiency, we would instead write a special function that takes these values in one pass, and it would have to perform some moderately complex book-keeping. In Haskell, the sort-then-take approach actually makes performance sense: laziness ensures that the list will only be sorted enough to find the three minimal elements.

Better yet, our Haskell code that operates so efficiently is tiny, and uses standard library functions.

minima k xs = take k (sort xs)

It can take a while to adjust to develop an intuitive feel for when lazy evaluation is important, but when we exploit it, the resulting code is often clean, brief, and efficient.

As the above example shows, an important aspect of Haskell's power lies in the compactness of the code we write. Compared to working in popular traditional languages, we often write Haskell code with a tenfold reduction in code size, in substantially less time, and with fewer bugs.

Enjoyment

We believe that it is easy to pick up the basics of Haskell programming, and that you will be able to successfully write small programs within a matter of hours or days.

Of course, programming in Haskell differs in huge ways from working in other languages, so mastering both the language and functional programming techniques does indeed require plenty of thought and practice.

Harking back to our own days of getting started with Haskell, the good news is that the fun begins early: it's simply an entertaining challenge to dig into a new language, in which so many commonplace ideas are different or missing, and to figure out how to write simple programs.

For us, the initial pleasure lasted as our experience grew and our understanding deepened. In other languages, it's difficult to see any connection between abstract mathematics and programming. In Haskell, not only have we imported some ideas from mathematics and put them to work, we've found that they're both surprisingly easy to pick up and a delight to deal with as we program.

Furthermore, we won't be putting any “brick walls” in your way: there are no especially difficult or gruesome techniques in this book that you must master in order to be able to program effectively.

That being said, Haskell is a rigorous language: it will make you do more of your thinking up front than other languages. It can take a little while to adjust to doing much of your debugging before you ever run your code, to satisfy the compiler that your program makes sense. But we think that you'll be astonished and pleased by the number of times your Haskell programs simply work on the first try afterwards.

What to expect from this book

We started this project because a growing number of people are using Haskell to solve everyday problems. Because Haskell has its roots in academia, few of the Haskell books that currently exist focus on the problems and techniques of everyday programming that we're interested in.

With this book, we want to show you how to use functional programming and Haskell to solve realistic problems. This is a hands-on book: every chapter contains dozens of code samples, and many contain complete applications. Here are a few examples of the libraries, techniques and tools we'll show you how to develop.

  • Create an application that downloads podcast episodes from the Internet, and stores its history in an SQL database.

  • Test your code in a new and powerful way. Understand which parts of your code are actually being covered by your tests.

  • Take a grainy phone camera snapshot of a barcode, and turn it into an identifier that you can use to query a library or bookseller's web site.

  • Write code that thrives on the web. Exchange data with servers and clients written in other languages using JSON notation. Develop a highly concurrent web server.

A little bit about you

What do we think you'll need to know before reading this book? We expect that you already know how to program, but if you've never done any functional programming, that's fine. If you've programmed in an expressive language like Python or Ruby, we think you'll pick Haskell up quite easily.

No matter what your level of experience, we've tried to anticipate your needs: we go out of our way to explain new and potentially tricky ideas in depth, usually with examples and images to drive our points home.

As a new Haskell programmer, you'll inevitably start out writing quite a bit of code by hand for which you could have used a library function or programming technique, had you just known of its existence. We've packed this book with information to help you to come up to speed as quickly as possible.

Of course, there will always be a few bumps along the road. If you start out anticipating an occasional surprise or difficulty along with the fun stuff, you'll have the best experience. Any rough patches you might hit won't last long.

As you become a more seasoned Haskell programmer, the way that you write code will change. Indeed, over the course of this book, the way that we present code will evolve, as we move from the basics of the language to increasingly powerful and productive features and techniques.

What to expect from Haskell

Haskell is a general purpose programming language. It was designed without any application niche in mind. Although it takes a strong stand on how programs should be written, it does not favour one problem domain over others.

While at its core, the language encourages a pure, lazy style of functional programming, this is the default, not the only option. Haskell also supports the more traditional models of procedural code and strict evaluation. Additionally, although the focus of the language is squarely on writing strongly typed programs, it is possible (though rarely seen) to write Haskell code in a dynamically typed manner.

Compared to traditional static languages

Statically typed languages have been the mainstay of the programming world for decades. Although Haskell is a statically typed language, its notion of what types are for, and what we can do with them, is much more flexible and powerful than traditional languages.

In addition, Haskell's type system is often unobtrusive: a Haskell compiler will automatically infer the type of an expression or function if we don't provide it. Compared to traditional static languages, to which we must spoon feed large amounts of type information, the combination of power and inference in Haskell's type system significantly reduces the clutter and redundancy of our code.

Several of Haskell's other features combine to further increase the amount of work we can fit into a screenful of text. As a result, it is not unusual for a Haskell program to require one tenth the number of lines of code as an equivalent written in a traditional language. With this come improvements in development time and agility: we can create reliable code quickly, and easily refactor it in response to changing requirements.

These productivity improvements are sometimes accompanied by a performance penalty when it comes to running code. It is not unusual for a Haskell program to run at a half to a quarter the speed of a comparable program written in a traditional language.

However, a substantial and increasing number of Haskell programs perform as well as (sometimes better than) their traditional counterparts. In part, this is due to advances in Haskell compilers and libraries, where progress is rapid and improvements benefit the entire community. Also, Haskell's huge edge in developer productivity gives us more opportunities to focus on algorithmic improvements.

Compared to modern dynamic languages

Over the past decade, dynamically typed and interpreted languages have become increasingly popular. They offer substantial benefits in developer productivity. Although this typically comes at the cost of a huge performance hit, for many programming tasks productivity trumps performance, or performance isn't a significant factor in any case.

Brevity is one area in which Haskell and dynamically typed languages perform similarly: in each case, you write much less code to solve a problem than in a traditional language. Programs are often around the same size in dynamically typed languages and Haskell.

When we consider runtime performance, Haskell almost always has a huge advantage. Code compiled by GHC is typically between 20 and 60 times faster than code run through a dynamic language's interpreter. GHC also provides an interpreter, so you can run scripts without compiling them.

Another big differentiator between dynamically typed languages and Haskell lies in the philosophy around types. A major reason for the popularity of dynamically typed languages is that only rarely do we need to explicitly mention types. Through automatic type inference, Haskell offers the same advantage.

However, beyond this surface level the differences run deep. In a dynamically typed language, we can create constructs that are difficult or impossible to express in a statically typed language. However, the same is true in reverse: with a type system as powerful as Haskell's, we can structure a program in a way that would be unmanageable or infeasible in a dynamically typed language.

It's important to recognise that each of these approaches involves tradeoffs. Very briefly put, the Haskell perspective emphasises safety, while the dynamically typed outlook favours flexibility. If someone had already discovered one way of thinking about types that was always best, we imagine that everyone would know about it by now.

Of course, we have our own opinions about which tradeoffs are more beneficial. Two of us have years of experience programming in dynamically typed languages. We love working with them; we still use them every day; but usually, we prefer Haskell. In our experience, Haskell starts to outshine a dynamically typed language once a project grows to a handful of thousands of lines of code.

Haskell in industry and open source

Here are just a few examples of large software systems that have been created in Haskell. Some of these are open source, while others are commercial products.

  • Innumerable compilers and compiler-related tools

  • Chip design software

  • A toolkit for music composition

  • Distributed revision control

  • Secure web middleware

Compilation, debugging, and performance analysis

For practical work, almost as important as a language itself is the ecosystem of libraries and tools around it. Haskell has a strong showing in this area.

The most widely used compiler, GHC, has been actively developed for over 15 years, and provides a mature and stable set of features.

  • It compiles to efficient native code on all major modern operating systems and CPU architectures

  • Easy deployment of compiled binaries, unencumbered by licensing restrictions

  • Interactive interpreter and debugger

  • Code coverage analysis

  • Detailed profiling of performance and memory usage

  • Thorough documentation

  • Massively scalable support for concurrent and multicore programming

Bundled and third party libraries

The GHC compiler ships with a collection of useful libraries. Here are a few of the common programming needs that these libraries address.

  • File I/O, and filesystem traversal and manipulation

  • Network client and server programming

  • Regular expressions and parsing

  • Concurrent programming

  • Automated testing

  • Sound and graphics

The Hackage package database is the Haskell community's collection of open source libraries and applications. Most libraries published on Hackage are licensed under liberal terms that permit both commercial and open source use. Some of the areas covered by open source libraries include the following.

  • Interfaces to all major open source and commercial databases

  • XML, HTML, and XQuery processing

  • Network and web client and server development

  • Desktop GUIs, including cross-platform toolkits

  • Support for Unicode and other text encodings

A brief sketch of Haskell's history

The history that led to the development of Haskell is rooted in mathematics and computer science research.

Prehistory

A few decades before modern computers were invented, the mathematician Alonzo Church developed a language named the lambda calculus. He intended it as a tool for investigating the foundations of mathematics. The first person to successfully capture the idea of using the lambda calculus to write software was John McCarthy, who created Lisp in 1958.

During the 1960s, computer scientists began to recognise and study the importance of the lambda calculus. Peter Landin and Christopher Strachey developed ideas about the foundations of programming languages: how to reason about what they do (operational semantics) and how to understand what they mean (denotational semantics).

In the early 1970s, Robin Milner created a more rigorous functional programming language named ML. While ML was developed to help with automated proofs of mathematical theorems, it gained a following for more general computing tasks.

The 1970s saw the emergence of lazy evaluation as a novel strategy. David Turner developed SASL and KRC, while Rod Burstall and John Darlington developed a NPL and Hope. NPL, KRC and ML influenced the development of several more languages in the 1980s, including Lazy ML, Clean, and Miranda.

Early antiquity

By the late 1980s, the efforts of researchers working on lazy functional languages were scattered across more than a dozen languages. Concerned by this diffusion of effort, a number of researchers decided to form a committee to design a common language. After three years of work, the committee published the Haskell 1.0 specification in 1990.

We are generally blind to the tired cliche of “design by committee” except when a counterexample is thrown our way, and the work of the Haskell committee is a beautiful example of the best a committee can do. They produced an elegant, considered language design, and succeeded in unifying the fractured efforts of their research community. Of the thicket of lazy functional languages that existed in 1990, only Clean and Haskell still exist.

Since its publication in 1990, the Haskell language standard has seen five revisions, most recently in 1998. Researchers have built around half a dozen implementations of the language. Of those, about half are still under active development.

During the 1990s, Haskell served two main purposes. On one side, it gave language researchers a stable way to experiment with making lazy functional programs run efficiently. Other researchers explored how to construct programs using lazy functional techniques.

The modern era

While these basic explorations of the 1990s proceeded, Haskell remained firmly an academic affair. The informal slogan of those inside the community was to “avoid success at all costs”. Few outsiders had heard of the language (or even functional programming) at all.

During this time, the mainstream programming world was experimenting with relatively small tweaks: from programming in C, to C++, to Java. Meanwhile, on the fringes, programmers were beginning to tinker with new, more expressive languages. Guido van Rossum designed Python, and Yukihiro Matsumoto developed Ruby.

As these newer languages began to seep into wider use, they spread some crucial ideas. The first was that programmers are perfectly capable of working in expressive languages; in fact, they flourish. The second was in part a byproduct of the rapid growth in raw computing power of that era: it's often smart to sacrifice some execution performance in exchange for a big increase in programmer productivity. Finally, the creators of these languages explicitly credited functional programming as a source of inspiration.

Over the past half a decade, Haskell has successfully escaped from academia, buoyed in part by the visibility of Python, Ruby, and even Javascript. The language now has a vibrant and fast-growing culture of open source and commercial users, and researchers continue to use it to push the boundaries of performance and expressiveness.

Helpful resources

As you work with Haskell, you're sure to have questions and want more information about things. Here are some Internet resources where you can look up information and interact with other Haskell programmers.

Reference material

  • The Haskell Hierarchical Libraries reference provides the reference to the standard library that comes with your compiler. This is probably the top item in the bookmarks for many Haskell programmers.

  • For questions about language syntax and features, the Haskell 98 Report describes the Haskell 98 language standard.

  • Various extensions to the language have become commonplace since the Haskell 98 Report was released. The GHC Users's Guide contains detailed documentation on the extensions supported by GHC, as well as some GHC-specific features.

  • Hoogle is the Haskell API search engine. It can find functions for you by name or by type.

Applications and libraries

If you're looking for a Haskell library to use for a particular task, or an application written in Haskell, check out the resources in this section.

  • The Haskell community maintains a central repository of open source Haskell libraries and applications. It's called Hackage, and it lets you search for software to download, or browse its collection by category.

  • The Haskell Wiki contains a section dedicated to information about particular Haskell libraries.

The Haskell community

There are a number of ways you can get in touch with other Haskell programmers, to ask questions, learn what other people are talking about, and simply do some social networking with your peers.

  • The first stop on your search for community resources should be the Haskell web site. This page contains the most current links to various communities and information, as well as a huge and actively maintained wiki.

  • Haskellers use a number of mailing lists for topical discussions. Of these, the most generally interesting is named haskell-cafe. It has a relaxed, friendly atmosphere, where professionals and academics rub shoulders with casual hackers and beginners.

  • For real-time chat, the Haskell IRC channel, named #haskell, is large and lively. Like haskell-cafe, the atmosphere stays friendly and helpful in spite of the huge number of concurrent users.

  • There are many local user groups, meetups, academic workshops, and the like; here is a list of the known user groups and workshops.

  • The Haskell Weekly News is a very-nearly-weekly summary of activities in the Haskell community. You can find pointers to interesting mailing list discussions, new software releases, and the like.

  • The Haskell Communities and Activities Report collects information about people that use Haskell, and what they are doing with it. It has been running for years, so it provides a good way to peer into Haskell's past.

Want to stay up to date? Subscribe to the comment feed for this chapter, or the entire book.

Copyright 2007 Bryan O'Sullivan, Don Stewart, and John Goerzen. This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 License. Icons by Paul Davey aka Mattahan.