[Haskell-cafe] Practical introduction to monads

David Roundy droundy at abridgegame.org
Tue Aug 2 18:15:22 EDT 2005


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=annotate

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


More information about the Haskell-Cafe mailing list