As part of my remedial Haskell learning process, I’ve been getting my feet wet once more with monads. Here are a few notes on the techniques that I’ve tried, and how I’ve fared with them. Not surprisingly, my first step was to try reading some tutorials. If you’ve looked, you may have noticed that the web is awash with monad tutorials. There’s something about monads that seems to compel people to write tutorials about them. They sound scary: what’s this chunk of category theory doing in my language soup? After a few nights of reading, but absorbing little, I concluded that this was getting me nowhere. I’m happy to concede that this was in large part my fault; I prefer taking things apart to reading about how they’re put together; and I have two little kids, so my attention is perforce limited to brief spans, right before bed. But I suspect that Sturgeon’s Revelation may have had more than a little to do with my indifferent level of enlightenment. My reaction was to abandon the tutorials, and start reading the source code of the Haskell prelude (the chunk of standard library that’s always available without you having to explicitly pull it in). To my delight, I found that the Maybe type was a monad; even better, it looked like it might be easy to use. Armed with a text editor and a Haskell interpreter, I wrote a simple parser and interpreter for a pattern language, and used the Maybe monad to represent the results of both parsing and matching. (In case you’re interested, I reimplemented the Unix fnmatch library call. It’s a nice, tidy problem that doesn’t require a full regexp engine to solve, and that provides a bit of useful functionality that’s not available through any standard Haskell library.) While I was doing this, I deliberately avoided Haskell’s “do” syntax, the better to give me an idea of what was really happening. And rather than try to follow the rickety exposition of a tutorial, I simply made lots of elementary mistakes. Each infinite loop and type error was my own shining beacon of stupid, lighting a step on the random walk towards slightly less stupid. At the end of a few hours of hacking, I had a nifty little piece of code going, complete with uses of the three monad functions. I was satisfied that I at least had some notion of the use of the Maybe monad, albeit in splendid isolation. This turned out to be an especially good place to start, because the Maybe datatype is incredibly simple, as are the monad functions defined on it. Once I was happy with the Maybe monad, I decided to try the State monad. My programming vehicle this time was much simpler than fnmatch; I just decided to count repeated instances of an item in a tree. This turned out to be a lucky choice, because I found State much harder to grasp than Maybe. (Perhaps this was because I was coming from the direction of reading the source code in a vacuum and trying to decide how to put the pieces together. I won’t be surprised if the “read the source” approach fails me at some point, but so far, so good.) This was an endeavour where Haskell’s brevity and type system really shone for me. Even though I had little initial idea of what I was doing, I was able to run my initial State-using code through the interpreter, have it point out something egregious that I was misunderstanding, and iteratively refine (I mean “rip to shreds and rewrite”) my code until I got it to actually work, all the while referring to the source for the State monad so that I could find functions like evalState, get, and put. The brevity of Haskell helped me here because the State monad is tiny; even though it’s much more complex than the Maybe monad, it’s still small enough that the source fits in a single editor window. And the type system was valuable not only because the interpreter could spank me whenever I was being dull-witted, but because I could read the type signatures of functions and actions around the State monad that I thought I might need, and tell whether they had a chance of doing what I wanted. Once I had a basic grasp of the Maybe and State monads, I found that going back and rereading the same tutorials that had initially baffled me had a profoundly different result. I now had a framework in which I could think usefully about what the tutorial authors were trying to tell me. (I also have stronger opinions as to which of the tutorials and references are best, but I’ll save those for another time.) After a few days of tinkering with them, monads are looking decidedly less scary to me. We’ll see if I’m still saying that after spending a little time with StateT and a few stacked monads, but getting my hands dirty has given me a degree of understanding that I could not have matched with reading. If monads still give you palpitations, I urge you to dive in, create a silly contrived problem for yourself, and just wallow with Maybe for a while.
Posted in haskell