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.
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.
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).
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.
First of all, you should probably pretend like you've never programmed before.
If you run into a word like return or class don't assume that you know what that means; chances are that you don't.
Here's a general idea of where you stand, depending on what languages you already know well:
So now that you have a general idea of where you stand, and are starting to worry about how weird Haskell is going to be, let's go through a quick (probably incomplete) list of the main distinctions between programming in Haskell and writing code in more "traditional" imperative programming languages.
- 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.
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.
- 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.
- 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.
- 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.
- 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.
- 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.
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.
- Learn you a Haskell for Great Good (The very best full-language tutorial, from the basics all the way out to the advanced stuff)
- Erik Meijer's Channel 9 Functional Programming Lectures (Recommended by a pro-active reader! This series of lectures appears to be a rather excellent introduction to functional programming with Haskell. This link takes you to an index of the microsoft pages themselves. There is also a link in the Video Lectures section below that takes you to a different index that includes downloads of slides, solutions, etc.)
- Hitchiker's Guide to Haskell (Kind of advanced, and throws you right in, but also gives a good idea of using the language top to bottom... compiling, IO, etc.)
- Write Yourself a Scheme in 48 Hours (One to tackle once you've got some of the basics under your belt, a nice example of writing a full project in Haskell).
- Roll your own IRC bot (Like Write Yourself a Scheme it flies a bit fast, but is a nice example of writing a project in Haskell and doing something cool
- Lisperati.com's Haskell Picnic (Probably a good one once you've got some experience reading code)
- 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
These steps are not strictly linear nor are they a perfect guide to learning the language. Everyone learns languages differently, so you should find some good books or tutorials for your skill level and goals (some good ones are listed above) and use them in parallel with this guide. The steps below are in the order we expect you to master the concepts, not in the order you'll see them.
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'll also probably want to have read chapters 1 and 2 of Learn you a Haskell, and/or chapters 1 - 7 of Real World Haskell and gotten some practice using the Prelude (Haskell's standard library).
- 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 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):
Two (advanced) places to focus in particular when studying laziness are the following:
- 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 <- getContents , 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.
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]
you can move on to defining your own types using
data, type, and
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
newtype operators; be able to compare and contrast them.
- You should be familiar with GHCi's
:i shortcut. Try
:i Num to get started.
The next big thing in your quest to understand Haskell is the Monad. Monad is a typeclass. So make sure you understand those first. If you don't have a good grasp of the core language, understanding monad examples on the internet will be very difficult. There are a ton of (mostly good) monad tutorials on the haskell wiki. Take a look at sections 8.1 and 8.3. Monad tutorials can normally be broken down into three categories:
The approach that you probably want to take is to start by skimming the "why" ones. Then you want to skim some code-based ones to get an idea of "what" a monad is in terms of programming. Before you start writing your own monads though, you should actually skip to our next section and do some I/O stuff as a way to practice using monads. Once you have a fairly good idea of what a monad is and how it might fit into a program, you should try to roll your own monad from scratch. We did that by building a limited Forth interpreter as one of our projects. Once you've then played with the internals of writing a monad, a good next step is to look through All About Monads' Catalog of Built-in Monads and try to play with their source code examples. Monads take a while to become "natural" so you'll mostly just want to read a lot of different tutorials, and try to write as much code as you can.
- Tutorials that explain the Why of Monads
- Tutorials where you'll actually see code
- People using monads to do cool things
Before moving on make sure you:
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!
The best thing you can do at this point is to try to find cool examples using IO to do things you care about on the internet or in whatever books you have. Trying (and failing at first) to write effective IO code in Haskell will teach you what you need to know pretty fast.
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:
Page content written by Gordon Sommers and CJ Carey.