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
There’s some interesting discussion on this post on Reddit – see
http://www.reddit.com/r/programming/comments/ybtd9/ (with a few other comments on http://www.reddit.com/r/haskell/comments/y87rh/ too).
It’s interesting that so much of the discussion is about monads, when the main point of the post was to try to put monads in perspective…
Oh! You are Paul Callaghan! Your name appears on the Home page of this site but not on the About page. Now I know which essay is the one you wrote. (I thought it was Functional Thinking for the Imperative Mind, so I guessed wrong.)
I was curious to see an essay so I followed the link to Issue 38. But I couldn’t figure out which essay it was, because I don’t know your name, and you don’t give the name for your essay or series of essays. (There was more than one article in Issue 38 about “functional thinking”.)
Callaghan’s 1st law used to be don’t break the abstraction until absolutely necessary for performance, and then only break it where you gain a measurable benefit. Is it now Callaghan’s 0th law, or are computers too fast for you these days?
Nah – I reclassified it as common sense (-:
While I love Haskell, I’m going to have to disagree with your first law. When it comes to normal program control flow, I think you’re spot on. But when it comes to intense numerical calculations (e.g. matrix multiplication), it’s very rare to find an elegant functional design that can compete with the version using mutable state. And sadly, I think this will always be the case.
Hopefully someone will prove me wrong though!
Thank you for those last words. I think I was looking for that kind of motivation to learn me a Haskell. Monads are scary.
It is good point of view. Monad is not essential part for pure FP but for communicating with Real World.
I like haskell but i use OCaml because GHC is too slow to build an big application compared with OCaml.
Best Regards!
Before monads, Haskell was using a continuation-based framework for IO, so monads are still not essential – though they are a lot easier to use than continuations!
At the risk of being off topic, are you aware that there’s a small Haskell NLP community? We’re not very organised (my fault) but I keep hoping we can get all these Haskell natural language people talking to each other. I know we’re out there!
http://projects.haskell.org/cgi-bin/mailman/listinfo/nlp
I work in generation myself, have a TAG based surface realiser on Hackage and about to put one out that does some very simple referring expression generation. As for the rest of Hackage NLP, there’s a bunch of little packages out there for some of the statistical stuff and also simple eg. tokenisers and sentence segmenters; but nothing quite like a Haskell NLTK yet.
Hi, yes I was aware (and have joined the list). Good to hear from you. I guess you know about http://homepages.inf.ed.ac.uk/wadler/realworld/natlangproc.html, which is the system I referred to. (Maybe I should try to get it open sourced?) I’ll also send you some refs to parsing resources – it seems that few people know about Happy’s GLR mode or X-Saiga!
Hadn’t seen X-Saiga… Seems you’re subsuming Sem1.lhs !
I think it’d be great! First because a parser is the sort of thing people seem to ask for all the time. Second, because other Haskellers work in parsing (though not necessarily in Haskell) and it be fun for them. Third because it’s nice to look at pre-monad Haskell code and perhaps one day have a dusting-off/modernisation effort (not necessarily to make things monadic of course)