Monad wrangling, and the joy of #haskell

Three days ago, I enthused about the Python community, and what a great help to me they were back in the day.

These days it’s Haskell that has my brain feeling too small, and I’ve just had my first experience of the Haskell community. I installed an IRC client for the first time in four years just so I could log on to the #haskell IRC channel. I’m happy to report that the experience was entirely positive.

For an imperative programmer, learning Haskell is initially hard because you have to stop thinking in terms of issuing instructions which will be performed in order, and start thinking in terms of composing pure functions (which have no side effects) together to Get Things Done. It’s weird at first, but ultimately very powerful, as it lends itself much more nicely to higher-order programming, lazy evaluation, actually composing programs out of reusable parts, etc. I’d say I’m starting to get a reasonable feel for that, although I’ve got a long way to go.

Unfortunately, a little later, you realise that there are cases where you need side-effects (eg input/output), which leads you into this whole sort-of-imperative side of Haskell, at the heart of which lie the hairy monad things. You totally can’t avoid this, because sooner or later you need to do I/O. Monadic I/O (and monads in general) look & feel imperative at first, but you soon hit barriers thinking like that, and ultimately really have to read stuff like The I/O Inside Tutorial, Tackling The Awkward Squad, etc. in order to understand what’s really going on, which is actually really clever, decidedly not imperative, and at some point turns into lambda calculus or category theory (take your pick).

It’s monads that I’ve been wrangling with lately. I’ve been trying to do a fairly simple I/O task: I have some directory containing some files; I want to operate on a subset of the files in that directory, for each of them reading the file and creating some data object representing its contents. The details aren’t important. Doing this in Python (say) is trivial. Doing it in Haskell has had me stuck for nearly a week. :-) I spent all day last Friday working through “I/O Inside”, and now understand monads much better than I did, and maybe half as well as I should (but maybe not even). That was all very informative and educational, but still didn’t answer my problem.

Anyway, long story short, tonight I installed an IRC client, went on #haskell, asked the question, and got an answer immediately and in a wonderfully friendly fashion. Full #haskell chat log for today is here if anyone’s interested, but in essence it turns out that mapM is what I need for this task. Sweet, and actually incredibly simple when you know it. I think a lot of Haskell is like that…

By the way, the #haskell channel has this neato lambdabot running, which among other handy functions, remembers and repeats amusing/apposite quotes when instructed to do so. Given the sad theory geek that I am becoming, this quote it kicked up tonight made me chortle:

Binkley: the sex is all in the operational semantics, denotational semantics only deals with love.

vincenz, 14:41:22