How to Learn Haskell

How This Guide Works

So you want learn Haskell, and somehow or another you've ended up at this page. Good! This isn't really a tutorial though. Maybe you could call it a meta-tutorial. Our goal is to give you a better idea of the big picture when it comes to learning Haskell. So, you should be using this tutorial in conjunction with other resources. On that note, we point to lots of them from this page, so don't worry if you're not sure where to start. We've selected useful resources, tried to make connections, and attempted to offer some sort of linearity. Hopefully you can use this guide to better navegate your way through the learning process. Good luck!

If you have any questions or comments, the authors would love to hear from you! Our emails are on the main page.

Starting Out

Make sure you understand the reasons for learning Haskell

Unlike some modern languages, Haskell is not a language you will pick up in two days and then be able to write your homework 10x faster in. Haskell will make you sweat to write simple programs, but it can also make writing things you thought were really complex quite a bit simpler. Mostly, it's a good learning experience since the patterns and ways of thinking you develop will serve you in any computer science work you do. Find some articles or blog posts about "Why Haskell" and try to get an idea of what the Haskell world is like. Some good places to start are listed on the page Why Functional Programming.

Installing and running Haskell

The first thing you should do is install a Haskell compiler/interpreter on your system. HUGS and GHC are the most common options. We recommend GHC for its power and flexibility. It seems to be the de-facto standard, so using it will give you the same platform as most online tutorial writers. One last option to check out is Try Haskell. It's an online, interactive interpreter with limited functionality that can be useful if you don't want to install anything. (Note: it's currently in alpha, and only offers a subset of the language).

The Haskell Wiki has an enormous collection of tutorials, papers, and other resources for the aspiring Haskeller.

Haskell in 5 Steps talks about how to get Haskell on your computer and start writing programs

Real World Haskell's guide to installing and running GHC

Editors & GHCI

To make the most of the code examples you find, you should set up a good editor environment for yourself. We tend to use emacs and vim. In emacs, haskell-mode lets you automatically load ghci and evaluate your whole file just by typing C-c C-l. If you prefer vim, you'll probably want one terminal running vim and a second running ghci. You can use :r to reload a file once it's loaded into ghci.

Raghu has pointed out that haskell-mode is much easier to set up in emacs than xemacs. It should be doable in xemacs, but if you're new to the emacs world, we recommend just using plain emacs instead of xemacs. Don't be confused by the names either, emacs also has a gui mode built on X if that's what you prefer; the fork between xemacs and emacs was more of an ideological one -- you'll have to consult google to find out more!

If you want to use GHCI, you should learn how to use it, check out The GHCI page on the Haskell wiki, and realize that you're always writing code in the I/O monad when using GHCI.

GHCI is kind of weird. I said it. But, it's weird because it's awesome. As you start studying Haskell you'll soon find out all about the distinction between writing code "in a monad" and writing code outside of one. To give you a quick example of what I mean, compare:

a = 5

let a = 5

Consider this section to be your warning that GHCI is a little strange. Because everything is in the I/O monad when you use GHCI (this sentence doesn't need to make sense to you yet), expect it to seem strange until you've started reading some of the main tutorials and books we've referenced. We recommend writing your code in text files until you've built up a little experience with I/O and feel comfortable writing code directly in GHCI.

The Basics

C, C++, Java : Haskell will probably blow your mind. The notion of classes is almost completely different, return doesn't mean what you think it does, the algorithmic patterns are distinct, you don't get loops, and code doesn't run in the order it's typed on the screen. What!? Yeah. It's pretty awesome.

: Haskell will probably blow your mind. The notion of classes is almost completely different, return doesn't mean what you think it does, the algorithmic patterns are distinct, you don't get loops, and code doesn't run in the order it's typed on the screen. What!? Yeah. It's pretty awesome. Python, Perl : You might be in the same boat as the previous group, but you may have run into some useful functions like reduce, map, etc. that use functions as first-class objects, and use this feature to abstract away some common looping patterns. This shows up all the time in Haskell. If you're a Perl whiz, who knows what you've run into, but depending on whether you write Perl like a C coder, or write Perl like a Lisp coder you may find yourself accordingly prepared.

: You might be in the same boat as the previous group, but you may have run into some useful functions like reduce, map, etc. that use functions as first-class objects, and use this feature to abstract away some common looping patterns. This shows up all the time in Haskell. If you're a Perl whiz, who knows what you've run into, but depending on whether you write Perl like a C coder, or write Perl like a Lisp coder you may find yourself accordingly prepared. Ruby : Ruby's mixins and duck-typing actually bear some similarities to Haskell's typeclass system, so lookout for parallels, but don't assume you know everything since Ruby is object oriented and Haskell is not. Another handy thing is that Ruby coders tend to use Ruby's inject, map, collect, etc. functions quite a bit, which all represent very common patterns in Haskell.

: Ruby's mixins and duck-typing actually bear some similarities to Haskell's typeclass system, so lookout for parallels, but don't assume you know everything since Ruby is object oriented and Haskell is not. Another handy thing is that Ruby coders tend to use Ruby's inject, map, collect, etc. functions quite a bit, which all represent very common patterns in Haskell. Scheme, Lisp : You'll probably have a good start on the basic functional design idioms. What will drive you insane will be the typesystem, though you will also probably learn to love it pretty fast.

: You'll probably have a good start on the basic functional design idioms. What will drive you insane will be the typesystem, though you will also probably learn to love it pretty fast. ML, OCaml: You've still got a few things to learn, but these languages aren't that different. The main distinction (which is not small) is Haskell's purity, which will also be freaking out everyone in the above groups.

Syntax is different, for all of the reasons below

Order of evaluation is non-intuitive. Haskell is lazy. This takes some getting used to, but fortunately most Haskell tutorials you'll find will try to explain it early on. Also, SICP section 3.5 can be useful (if you're willing to learn some Scheme).

The notion of types is not the same. In most languages a variables type is just a way of defining how it's represented in the machine as bits. In Haskell a type is more general and can include a function signature, an enumeration, a tuple, a list, or a composite data type.

The notion of classes is not the same. Typeclasses in Haskell are a bit like Java's interfaces, or Common Lisp's generic method specifications. Fortunately, there are some good tutorials we can point you at later, including Learn you a Haskell.

Haskell is pure. Good explanations exist, and you're guaranteed to find them. Expect this to make you debug most of your functions a lot less, but also to make you struggle for a long time with writing simple I/O and state.

Common Patterns in Haskell Code

Before you dive into the details, we think it will serve you to have a basic understanding of some common functional idioms, mostly for dealing with lists of data. This tend to show up frequently in Haskell code, and if you're used to for loops, you might be caught off guard. These are all examples of functional programming's verb-centric style.

First of all, Haskell does have arrays, but they're almost never a good idea. Almost everything is done with lists, which are primitives in the language. Even strings are just lists of characters, so any list function is equally applicable to a string. So how do you iterate over your non-arrays and do things? Usually you'll use recursion. Essentially, you grab the first element from your list, do something, and then re-call your function on the remainder of your list. Most of the time, what you're doing fits into one of the following common patterns:

Map : mapping a function over a list means calling that function on each of the items in the list, and generating a new list from the results.

: mapping a function over a list means calling that function on each of the items in the list, and generating a new list from the results. Fold : folding a function over a list means recursively calling it with its previous return (or a given initial value) along with the next element in the list. A good example is sum, which can be expressed as: fold (+) 0 list . Essentially, you start with 0, then add the first element of the list. Now you add the next item to that result, and then the next item to the new result, and so on, until you run out of items and have accumulated the sum of all the elements as your result. In Haskell you can fold from the left or from the right; you'll figure out the difference later.

: folding a function over a list means recursively calling it with its previous return (or a given initial value) along with the next element in the list. A good example is sum, which can be expressed as: . Essentially, you start with 0, then add the first element of the list. Now you add the next item to that result, and then the next item to the new result, and so on, until you run out of items and have accumulated the sum of all the elements as your result. In Haskell you can fold from the left or from the right; you'll figure out the difference later. Filter: filtering a list with a function involves calling some function on every item in your list, and collecting just the items for which that function returns true. So for instance, you can filter all the even numbers from a list of integers this way, or all the valid positions from a list of game states.

Principal Resources

Below are some of the best general language resources we've found; using these resources (or ones like them) is how you'll learn Haskell.

The Haskell Wikibook (Has some very good pages at the moment on various topics, especially some of the more advanced stuff)

Real World Haskell (A pretty good resource, and freely available online -- has some cool projects and code examples, just don't expect it to teach you the language on its own)

#haskell on irc.freenode.net is a terrific place with terrific people. Stop by and say hi!

The Steps to Learning Haskell

Syntax

The first thing you have to master is syntax if you want to read Haskell code. We don't suggest trying to learn syntax on its own, but before trying to tackle more advanced features of the language you should have a good understanding of all the strange syntax Haskell has to offer. A good guide is the Tour of the Haskell Syntax.

Commonly Used Functions & Basic Programming Techniques

You should be able to understand and tinker with the breadcrumbs up to RPN.

You should attempt problems 1 - 20 of H99. Try to use fold, map, the . operator, and other higher-order concepts when you can, to really immerse yourself in "the Haskell way".

Laziness

Laziness isn't that tricky of a concept, but it can lead to some pretty strange (and beautiful) things so make sure you have a good grasp of it. If you read any book or full-language tutorial it's guaranteed to talk about laziness, but for the lazy (hah!) the following resources offer concise introductory explanations of Haskell's laziness (in order of depth):

Using laziness to define sequences. Check out this breadcrumb and this, more advanced one and make sure you understand this. Try implementing a list of factorials, or a list of primes on your own. SICP's stream chapter, especially the lazy part is full of good examples and practice problems that are very applicable to Haskell.

File I/O -- don't worry about this if you haven't run into I/O yet. Laziness in IO has some interesting consequences. If you say text , that evaluates instantly, but then as you you read text from text the file gets read retroactively. The bad consequence is that sometimes Haskell needs special care if you're reading really big files since techniques like the above can get weird when you exhaust the available cache memory.

Types

The type system can be deceptively simple since it's relatively easy to define your own data types in Haskell and do other routine things. Don't let yourself be fooled though; it's in fact quite deep and thorough understandings of typeclasses, newtype, and currying are essential to using Haskell effectively and to understanding the more advanced facets of the language. If you haven't already, be sure to read chapter 2 of Real World Haskell for an overview of how Haskell handles types. So does Learn you a Haskell. Once you can understand things like:

foo :: Int -> [Char] -> (a,b) -> ((a,b) -> Int -> Char) -> [Char]

data, type,

newtype

Learn you a Haskell has an excellent chapter on custom typeclasses and types. Reading this chapter should give you a much more thorough understanding of types and data in Haskell. Lastly, be sure you understand newtype, especially when used like this since it's a pretty common pattern in monad definitions and uses. A good example of that case is in this section of Real World Haskell.

You should be able to understand and tinker with related breadcrumbs.

You should know the data , type , and newtype operators; be able to compare and contrast them.

, , and operators; be able to compare and contrast them. You should be familiar with GHCi's :i shortcut. Try :i Num to get started.

Before moving on make sure you:

I/O

IO is essential to writing useful programs, and also a terrific first exposure to using monads in your Haskell programs. Good resources are the following, but keep in mind that the best thing to do, as always, is write your own code!

Advanced Stuff and Further Reading

Having learned everything mentioned so far, be aware that there's still a ton of stuff to learn. Some places to go from here:

Monad transformers

Haskell "idioms"

Arrows

Look at the libraries available in Hackage and mess around with them

Look for cool Haskell projects on the internet and check out their code