
On Tue, Aug 02, 2005 at 09:03:49PM +0100, Paul Moore wrote:
I've started learning Haskell, and I'm going through all the tutorial material I can find - there's a lot of good stuff available.
One thing I haven't found a really good discussion of, is practical examples of building monads. There's plenty of discussion of the IO monad, and the state monad, and a lot of good theory on monads, but although I've seen tantalising statements about how powerful the ability to define your own monads can be, but no really concrete examples - something along the lines of
A very nice simple starting monad from the Prelude to consider when thinking about these things is Maybe. It was a long time before I realized how nice the monad interface to Maybe is. If you have a bunch of calculations that might fail (and return Nothing in that case), you can convert case f a of Nothing -> Nothing Just b -> case g b of Nothing -> Nothing Just (c, d) -> ... into do b <- f a (c, d) <- g b ... which is much more comprehensible (and equivalent to the above). It took me a long time before I realized I could do this, and as a result I had a lot of nested case statements regarding Maybes. Actually, I had even implemented my own mplus operator for Maybe (only of course it wasn't called that). For more complicated practical examples (and only sporadically documented), you could look at some of the darcs source code. DarcsIO defines a monadic class, which has both IO and other versions. FilePathMonad is a pretty simple monad that is in those classes, and allows you to apply patches just to a list of FilePaths. The other big DarcsIO-related monad is the SlurpMonad, defined in SlurpDirectory, which is a tad ugly, but does show off the niceness of defining a uniform monadic interface. PatchCommute defines a Maybe-like monad called Perhaps, which has three states, success, failure and unknown, for calculations where "failure" doesn't mean a mistake but rather an answer (the patches don't commute). This is just a tad weird, but seems to work pretty well. The Perhaps monad has a conversion with the Maybe monad which I actually use most of the time. If you want to see lots of usage of Perhaps, you could check out the darcs-conflicts branch (which has the new conflictor code): http://abridgegame.org/cgi-bin/darcs.cgi/darcs-unstable/PatchCommute.lhs?c=a... There are also in darcs a couple of parser monads (lazy and strict) and probably a few more monads hanging around that I haven't thought of. In short, there really are nice practical uses non-IO monads. -- David Roundy