I Recommend These for Learning Haskell

Albert Y. C. Lai, trebla [at] vex [dot] net
March 25, 2021

In Chris Allen’s talk he rightfully critiqued that experienced Haskell people recommend learning material that they themselves haven’t actually used. I’m going to heed that advice and recommend only material that I have actually used, or consulted, or at least examined.

Ironically, this means I won’t be commenting on the book Chris Allen himself co-authored, Haskell Programming from First Principles, since I have never read it!

Below, I list the pieces of work that I actually learned from when I was a beginner, and additional pieces that I consulted or examined later (some I still consult today when it’s my turn to teach). In all cases, I also say a few words on their traits, so perhaps you can estimate how well they may suit you.

A Gentle Introduction to Haskell

A Gentle Introduction to Haskell is the main piece I learned Haskell from.

It is brief, and also only introductory on the harder topics (for example monads; see the next two sources for what I learned more about monads from). It does not have exercises.

These traits never bothered me. My learning habit is that every time I read a point, I stop and think up small experiments to stress-test “is this really true?”, or, more realistically, clearly it is true but “what if I’m misreading it?”. If examples are already provided, I mutate them to check what point they’re making, or really whether I see their point.

To be sure, lack of insightful exercises is a shortcoming; my own experimentation only mitigates it, not make up for it. But the other trait, briefness, is because this is a tutorial, not a full book or course.

And here are two things in it that I think are poorly done:

Monads for Functional Programming

Phil Wadler’s summer school lecture notes Monads for Functional Programming is the monad tutorial I wish I wrote—driven by testable code and reason, not warm fuzzy analogies. It uses 4 scenerios to give 4 basic examples of monads, building up to the general idea and definition. And then it describes more scenerios and applications.

Its shortcoming is that its notation is outdated. For example, it uses “★” for what we have been writing “>>=” for many years.

Monadic Parsing in Haskell

Graham Hutton and Erik Meijer’s paper Monadic Parsing in Haskell is the final straw that got me to understand monads. Or perhaps not so much last straw as coincidental to my own growth. Or perhaps I had understood monads all along, the last straw was for acceptance.

The striking thing is that a lot of people I have talked to, both experienced Haskell people and my own students, have the same sentiment. It does not have to be Hutton and Meijer’s version; any similar story does the job. Wadler’s lecture notes above include one. Bird’s book and Hutton’s book below have it, too, and show code that builds today.

Its shortcoming is that its code is outdated by changes to the Haskell standard library since then. Notably: you must also make its Parser type an instance of both Functor and Applicative; the MonadZero class is no more, its mzeo method is now in the MonadPlus class; some occurrences of ++, but not all, are now mplus.

If you want to read the extended, technical report version, Monadic Parsing Combinators, beware that the code there won’t compile as Haskell. (It’s Gofer, similar but has different rules.)

The Haskell School of Expression

If you are tired of string I/O and looking for a book that teaches programming by making pictures and music, that’s Paul Hudak’s «The Haskell School of Expression». Unsurprisingly it is also pretty hands-on. And it does not have the flaw of the average hands-on book: It does not shy away from teaching you to reason about Haskell code by doing algebra (the whole point of going purely functional).

Its shortcoming is that once again its code is outdated. The library you would need to run its code is out of sync with today’s Haskell ecosystem at large. But don’t blame it on the author, he passed away in 2015.

Two Similar Books: Bird’s And Hutton’s

From time to time I consult two books, Richard Bird’s «Thinking Functionally with Haskell» and Graham Hutton’s «Programming in Haskell (2nd edition)». Hutton also has lecture videos for the two courses corresponding to the two parts of his textbook: part 1 YouTube playlist and part 2 YouTube playlist.

They have very similar topics and the same traits, so I will talk about them together.

They are concise. This is different from the “brief” I used to describe «The Gentle Introduction». My “brief” means just being a starting point, as a tutorial should. My “concise” means it may (or may not) be thorough (e.g., make more points, show more examples, have more exercises), but it has no drawn-out fillers (recall your 2000-page college textbook, of which you highlighted only 1%). So you would still be well advised to take them slowly, stop at each point or example, think how to check your understanding, don’t just scroll through, don’t do speed-reading.

Both authors are researchers in using algebra to reason about programs, so it is not a surprise that they teach it in their books (to the extent justifiable for Haskell books of course), and like I said this topic is a must-have, or else no point bothering with a purely functional language.

Both books walk you through a few mini projects:

I am happy to say that both explain lazy evaluation: what it does, what kind of nice code it enables, how it also causes space inefficiency for the opposite kind of code, and what Haskell provides to fix that. They are not as thorough as I would like (would be nice to have more examples of lazy evaluation steps and more exercises), but adequate and a good start, especially given: This is a topic that some authors of Haskell books/tutorials don’t attempt because they know that they don’t understand it, and most bloggers do poorly (too ad hoc, too brief, too handwavy, too wrong) because they don’t know that they don’t understand it either.

I think that their explanations of monads are a bit on the brief side. You would still benefit from Wadler’s monad lecture notes as a follow-up. Fortunately, they also tell the monadic parsing story, and with code that builds today.

Unfortunately, neither book covers monad transformers. (Bird’s older book did.)

Problem Set by Tony Morris et al.

If learning is not a spectator sport, the problem set by Tony Morris et al. certainly takes it to the extreme. This is a problem set associated with the course that Morris teaches. It has gone through two name changes already because it moves with Morris: It was first the “NICTA course”, then the “Data61 course”, and now the “System F course”.

I say that it takes “learning is not a spectator sport” to the extreme because, whereas other courses, tutorials, and books would explain the code of some common functions (so you’re a spectator here) before asking you to code up some others, this problem set asks you to code up all of them at the onset. You are never a spectator in this problem set.

Evidently, it is steep on its own because it is not meant to be on its own, it is meant to be used in an in-person course that includes in-person guidance. If you use it on your own, you need to make up for it by studying at least another tutorial, and most importantly, finding someone to talk to. For the latter, the readme already lists a few places; here is one more: the IRC channel #haskell on Freenode.

The Haskell Wikibook

For a source that is both free and has the expanse of a book, nothing beats the Haskell Wikibook (or pessimistically, there is no other choice). Although I haven’t checked it thoroughly, I have found the basic parts good enough that I refer my students to them (at least before they need further help).

It has a small amount of exercises, far fewer than a proper textbook, but more than none. (Keep in mind that the authors receive no compensation.)

One of its strengths is that it goes on to some advanced topics; not all, but enough to satisfy most of your curiosity, and certainly exceeds all other textbooks. Now, again, this is volunteer work, some topics are done well, but some others are very sketchy.

The one advanced topic that I’m impressed that it covers, and covers well enough, is denotational semantics. (Denotational semantics is why you hear people say “bottom”, “non-strict”, and “least fixed point”.) I think here you will find a good introduction, though you will need more examples and exercises. This is a diredly needed topic, but also a diredly feared topic, feared even by bloggers who don’t know that they don’t know. When the time comes that you look for an explanation of denotational semantics, I recommend this one. (Pessimistically because there is no other choice that both does justice and is accessible.) (Until I write mine that is more well-motivated, more concise, and has more examples and exercises.)

One topic that I think the wikibook doesn’t do well is lazy evaluation. It postpones the topic to the advanced level (but you need to learn it to solve intermediate level problems), its explanation unnecessarily makes some genuinely advanced topics as prerequsite (e.g., graph reduction), and the part about how to fix space inefficiency is a stub. The textbooks by Bird and Hutton are much better on this topic.

Epilogue: The 3rd Book You Study

Someone in a math channel on IRC made the very keen and true observation that the 3rd calculus textbook you study is the best calculus textbook.

Please take a moment to meditate on the logical conclusion. The determining factor is not with any of the books; it is with you. The underlying phenomenon is that learning requires a good dose of repetition, sometimes even repetition just to get you to tune in.

This is going to be true of learning Haskell as well. Actually, even worse: If you are deeply entrenchedly experienced in imperative and/or OO programming, almost all of what you considered universal truth will be defied by Haskell (or purely functional programming in general), you will be in shock for a long, long time, you will probably need many more repetitions than 3 before you begin to tune in to the anti-imperative model that all teaching materials are trying to present.

Please anticipate that any single piece of work may be insufficient to help you learn and understand Haskell. You will very likely need multiple of them, in sequence or in parallel.


I have more Haskell Notes and Examples