I’ve been fortunate enough to get some of my ‘essays’ into PragPub magazine, starting with an overview of how functional programmers think and how they use their languages. See Issue 38 for the first installment. Subsequent months should see articles on types and testing, practical programming, refactoring, and dependent types. And yes, eventually something about monads.
When planning these articles, I’ve been reading around some of the recent books and tutorials in Haskell and Ruby – mainly to get a feel for what people might understand and for places where they might run into stumbling blocks. I’m still not entirely satisfied with current material on Haskell, which is one reason I started to write these pieces. The ‘expert’ writing on Haskell is fairly dry, a bit too academic, and I rarely see much of the enjoyment and wonder that keeps me programming in Haskell even after 20+ years. (I love coding, it must be said, and I like to use tools that let me have fun and do great things.)
The other main camp is the people learning Haskell and trying to explain their experiences to others. Though there’s some very useful and interesting accounts out there, they generally also miss some important ideas or put too much emphasis on certain details (and I suspect that the expert camp is partly to blame, for not explaining some ideas as well as they could).
There’s two main culprits: (a) a sense of denial and (b) monads.
Denial!
By denial, I mean the suggestion that Haskell etc denies itself the use of things like mutable state that everyone else takes for granted, and that a lot of what follows is an attempt to cope with our asceticism. My perspective is different: I see Haskell as starting from a different set of assumptions and arriving at a different place to the mainstream. Instead of us needing higher order functions to cope with not having mutable state, instead, I see HOFs as a useful tool for manipulating the data, and flexibility of HOFs means that we don’t need to rely on things like
mutable state so much. Hell, I’ll stick my neck out and propose a new law:
Callaghan’s 1st Law: the need for mutable state in a language is inversely proportional to its flexibility in manipulating data
Put another way, mutable state is a lower-level idea and becomes less important when your language supports higher-level ways of working.
A similar comment applies to our use of a type system. We’re not doing it to put ourselves in a strait-jacket for any silly or conservative reasons. Experienced Haskell programmers know that the type system is a tool for getting work done, and a great language for playing with designs, and they exploit these aspects to help them get their work done. Plus, if things get in the way, we often find ways to remove the obstacles.
So basically, I think FP and Haskell is more about opportunity than denial. We’re super-liberal!
Monads!
There’s a view that Haskell is 99% monads (or thereabouts), and that monads are some arcane mystical concept which only a few can master. Bullshit to both!
I remember the time before monads. It _was not_ a barren wasteland, where all we could do is write programs to build trees and not communicate with the outside world. We really could do real world stuff, including file operations, console IO, IPC, though it was a bit clumsy in places. At that time, I was doing PhD work on a large Natural Language Processing system, around 60k lines of Haskell and so one of the largest programs of its time. The program could process and analyze Wall Street Journal articles in a few seconds and build a complex semantic representation of the story, and didn’t use a single monad.
It was however a time of exploration, when researchers explored various ideas to find a good way of both having our cake and eating it. Monads are one of the solutions they found, and essentially gave us a small but flexible API for working with “computations” (like IO operations or state modifications, or various combinations thereof) as opposed to simple data values, and did so elegantly _within_ the standard langage (ie. no ad hoc extensions needed). It got even better when syntactic sugar was added.
This simple idea provided an excellent structuring pattern to tame a lot of
clumsy code, and even more useful, gave us a solid framework for exploring more powerful ideas.
So monads are highly useful for some aspects of programming work, but they are certainly not an essential or core part. I estimate that 50-80% of most large Haskell programs do not involve monads at all – they are just pure data manipulation. Of the remainder, the monad use is mostly straightforward and follows certain common idioms. Real scary stuff is pretty rare.
Last words
As a new explorer (very warm welcome, by the way!), when you look at Haskell material you may see some very unusual or scary-looking stuff. But do bear in mind that a lot of it is just playing around with abstractions on top of the core language, and probably does translate to something more intelligible. Try to work out what is being said about the data being manipulated, and then it might not look so bad.
Another thing that works is to avoid writing code for things you know how to do, and instead try to write code for other things. For example, try thinking and playing with various tree operations, like leaf counting, traversals, map/foldfilter… Then, you’ll be less tempted to slip into imperative mode.
I also recommend Graham Hutton’s “Programming in Haskell” as the best book introduction to the language. It is a brisk but surprisingly complete introduction to Haskell and related techniques, and parts of it remind me of K&R. However, it is still an academic textbook for an introductory course, and can be thin on the pragmatics and wider picture.
There’s also a thread on the PragPub forums where I’m collecting ideas/requests for future articles. Please feel free to add comments there – http://forums.pragprog.com/forums/109/topics/10889