Review: Learn You a Haskell for Great Good!
Learn You a Haskell for Great Good! (A Beginner's Guide) by Miran Lipovača, published by No Starch Press (2011). No Starch was kind enough to send me an advance copy for review.
Haskell books for "real programmers" are still thin on the ground, being limited at the moment to Real World Haskell (2008) and possibly Programming in Haskell (2007). As its introduction states, this book is aimed at existing programmers who are currently fluent in something like Java, C++, or Python, and would like to learn Haskell.
I put my take on the traditional discussion of why you should consider learning Haskell in another blog post, so we can get on with the review here.
The hardest thing about learning Haskell with no previous functional experience is bootstrapping the strong foundation that you've long since taken for granted in your imperative language. If you don't have this strong grasp of the fundamentals, then every line of code is an invitation to get stuck on some subtle issue, and you'll never have the fluency that great work requires until you have that foundation.
This book is the best way I know to obtain the Haskell foundation you need for fluency.
When I first opened the book and hit the table of contents and noticed that the book almost ends at Monads (chapters 13 and 14 out of 15 total), I was unsure what value this book could have. "Everybody" knows that's where Haskell begins, right? But that's also the problem; most intros and tutorials try to get to them as quickly as possible and thus fail to lay a strong foundation, which has resulted in the perception that they are some weird thing requiring bizarre metaphors and/or is just a crazy hack to deal with IO. You will know better than that by the time you finish LYAH.
Chapters 1 through 4 are dedicated to laying out the basics that you need to do anything in Haskell: Basic function syntax, the basics of the type system and the basic types the language comes with, and the basics of recursion. The recursion chapter takes the approach of carefully explaining how several of the core list functions are implemented recursively. Surprisingly, a discussion of tail recursion is left out. I'm not sure how I feel about that. It is an unfortunate thing to have to hit a beginner with, but it is also unfortunate to leave them unprepared to deal with the problem of stack overflow if it comes up. But otherwise the recursion chapter is solid.
Chapter 5 introduces higher order functions, then with modules and new custom typeclasses the work of actually creating programs is covered. Chapters 8 and 9 cover IO, albeit thinly; it progresses only just beyond reading and writing text files line-by-line, touching on using the random functions and bytestrings. Chapter 10 implements an RPN calculator in a functional manner, and also solves a min-path problem for a restricted certain sort of graph
Then we get to what I believe is the true raison d'etre for this book, which is chapters 11 through 14. Having laid the necessary foundation for the topics in the previous chapters, chapter 11 begins with a clear-as-a-bell explanation of functors, then applicative functors. It then builds up to monoids in chapter 12, monads in general in chapter 13, then in chapter 14 makes the reader, writer, and state monad seem not only simple but obvious, something I was not sure was possible.
This sequence alone is worth the price of entry. Over the past couple of years I had been assembling my own understanding of these topics piecemeal via the internet and other documentation. I've read monad "tutorials" numbering in the low dozens. In a handful of hours, these chapters blew what turned out to be my rickety assemblage of concepts apart and replaced them with a solid understanding of what is going on with them, and why. This is the foundation that the book gives you. This is the foundation that will allow the reader to step out into the broader realm of Haskell libraries and applications and see familiar things used in new ways instead of a mass of confusion. Learn You a Haskell for Great Good! removes the magic from Haskell, and replaces it with awesome.
After that adventure, chapter 15 on zippers seems anticlimactic and random, in that it's a good chapter for what it is but seems to be just sort of hanging out. Hopefully it is the harbinger of Learn You Yet More Haskell For Greater Good!
All that said, the subtitle "A Beginner's Guide" is accurate. Many topics normally considered basic are left uncovered, such as tail recursion. Exception handling is mostly limited to Control.Exception.bracketOnError. LYAH at no point discusses how Haskell's syntax uses whitespace, which based on my experience can cause some problems in the beginner phase, even if you are fluent in Python to start with. Probably worst of all, nothing is said about any way of debugging your programs, not even to the extent that you may need for the examples given. This is not your all-in-one guide to Haskell. But I think that someone who takes the time to read this book twice and work through the examples will be in a better position to start reading about monad transformers than someone who has read a work that blasted through everything else as quickly as possible to get to that point. The table of contents may be relatively thin, but you will grok the things in it when you are done.
I can't end this review without also calling out the excellent index. I doubt there's much you might want to look up later that you will not find in there. It also does not contain the obvious recursion joke, or any variant thereof.
Whether you add or deduct points for that is up to you.
The style is pleasantly conversational, which offsets the formality of the topic nicely. Doodles adorn the text here and there. How can you not say Hello to that World? It seems to me they start out directly connected to the text, then become increasingly more obscure as the book goes on, until I lose the train entirely in the Zipper chapter. What is Captain Picard doing on page 352? I don't know. But he's there.
Should you buy this book? If you are already clear on the relationships between applicative functors, monoids, and monads and their practical use, then this book offers you little. If you're actually on the fence as to whether or not you want to learn Haskell, this book doesn't "sell" it so much as simply start teaching it; you may want to at least browse over Real World Haskell first. But if you fit the books stated target audience, you want to learn Haskell, and you value your time, I solidly recommend this book, and recommend starting with LYAH before Real World Haskell. You can theoretically get the same foundation from free resources online, but it will take you much longer. (Believe me. I know.)
Update: This is apparently also available at http://learnyouahaskell.com. I had thought that was a much older version of this, but apparently not so old. It's not quite identical to the copy I have but it's close.
As a parenthetical side note, seeing Haskell through the eyes of a beginner has reminded me how badly Haskell needs an equivalent of Python 3000. Far too often this book had to stop to discuss the naming of various functions, or explain why there are so many "map" functions, or why we have fmap and map and all these utterly differently named variants for similar concepts, or how Applicative isn't a prerequisite for Monad. And in each case this is exactly the sort of thing that can trip up a beginner for hours. If you are going to use this book, I would seriously recommend that you listen near the beginning when it tells you where you can get more Haskell help, especially the IRC channel. Do take the time to try to figure out what the error messages Haskell emits means yourself for a few minutes before just giving up, but don't be afraid to call in the cavalry. And perhaps if it's been a couple of years since 2011 we'll have this cleaned up by the time you're reading this.