Owing to Haskell’s youth and its origins in academia, research papers are often best for learning some aspects of the language.
- On Lisp by Paul Graham
Though Lisp is dynamically typed, impure, and eagerly evaluated, this book is worth reading for its historical importance, for its excellent introduction to functional programming and metaprogramming, and for its code excerpts. Translating it to Haskell, or attempting to, is a good exercise.
- Why Functional Programming Matters by John Hughes
This classic presents concrete evidence of the power and simplicity of pure functional programming. Translating the example code to Haskell is another good exercise.
- Proofs are Programs: 19th Century Logic and 21st Century Computing by Philip Wadler
If we care about reliable software, we must study the foundations of mathematics.
- Tacking the Awkward Squad: monadic input/output, concurrency, exceptions, and foreign-language calls in Haskell by Simon Peyton Jones
One might think that Haskell is great for research and teaching, but perhaps not as great for practical applications because of messy real-world complications. On the contrary, it turns out Haskell can elegantly resolve these complications.
- Applicative programming with effects by Conor McBride and Ross Paterson
Introduces applicative functors, a useful abstraction lying between functors and monads. Indeed, these are so useful that GHC has elevated applicatives to their rightful place in the pantheon alongside functors and monads.
- Lazy Functional State Threads by John Launchbury and Simon L Peyton Jones
Some data structures work best when mutable, and a clever extension of the type system lets us operate on them in Haskell.
- Purely Functional Data Structures by Chris Okasaki
Lazy evaluation and immutability can be helpful when designing data structures. Code is simpler, and we gain persistence. This PhD thesis later became a book.
- Beautiful concurrency by Simon Peyton Jones
Introduces Software Transactional Memory (STM), which can neatly solve tricky concurrency problems.
- Binary Lambda Calculus and Combinatory Logic by John Tromp
Among other things, introduces some theoretical underpinnings of Haskell.
- Template Meta-programming for Haskell by Tim Sheard and Simon Peyton Jones
Sooner or later, we want programs to generate code. This paper shows how it’s done in Haskell.
- The Glasgow Haskell Compiler by Simon Marlow and Simon Peyton Jones
Fascinating overview of the inner workings of an industrial-strength Haskell compiler. Especially recommended for those who care about performance.
- Warp by Kazu Yamamoto, Michael Snoyman, and Andreas Voellmy
Haskell’s green threads suit servers, but lazy I/O causes problems. Fortunately, there are clean fixes.
- Lecture notes on how a Haskell compiler works by David Terei, and on the RTS by Edward Z. Yang
Good overviews. I wrote an interpreter for a subset of Core by following references in these slides.
- A History of Haskell: being lazy with class by Paul Hudak, John Hughes, Simon Peyton Jones, and Philip Wadler
The amusing anecdotes within are effective teachers of some of the most technical parts of Haskell. How do data and newtype differ? Why does show  work in GHCi, but not in a program unless accompanied by a type declaration? Did you know pattern matching in let and where differs to pattern matching in case and lambdas?
- Write You a Haskell by Stephen Diehl
A promising book.
- Software Foundations by Benjamin Pierce, Chris Casinghino, Marco Gaboardi, Michael Greenberg, Cătălin Hriţcu, Vilhelm Sjöberg, Brent Yorgey
Functional programming “serves as a bridge between logic and computer science” which can ultimately guarantee bug-free code.
Some books I liked (but are unfortunately not freely available):