[Haskell-cafe] Teaching Monads

Derek Elkins derek.a.elkins at gmail.com
Sat Jun 7 12:54:18 EDT 2008

On Sat, 2008-06-07 at 00:05 -0400, Ronald Guida wrote:
> Monads in Haskell are a topic that I, like most beginners, find
> difficult and "mind-twisting".  Now that I think I understand monads,
> they seem to be very simple; I've read that this is a common
> experience.
> So I wonder, what would it take to help beginners catch on with a
> minimum of fuss or frustration?  The plethora of monad tutorials out
> there is clear evidence that plenty of others have wondered the same
> thing.
> What made monads "click" for me is when I understood the following
> things:
> 1. When monads are being used, closures are almost always involved.
> 2. These closures naturally arise when desugaring do-syntax.
>  do x1 <- m1               m1 >>= (\x1 ->
>     x2 <- m2               m2 >>= (\x2 ->          [Eq1]
>     x3 <- m3               m3 >>= (\x3 ->
>     return (f x1 x2 x3)    return (f x1 x2 x3))))
> 3. These closures are extremely similar to the closures that arise
>    when desugaring let-syntax.
>  let x1 = f1 in            f1 -$ (\x1 ->      Where:
>    let x2 = f2 in          f2 -$ (\x2 ->      (-$) :: a -> (a -> b) -> b
>      let x3 = f3 in        f3 -$ (\x3 ->      x -$ f = f x
>        f x1 x2 x3          f x1 x2 x3)))
> 4. While I can think of a monad as a fancy container that holds an
>    element of type "t", it might be more accurate to think of a monad
>    as a container that merely displays the type "t" as a label for its
>    contents. The container might hold one object of type "t", or it
>    might hold several.  It might not be holding any at all.  Perhaps
>    the container /never/ holds an object of type "t", but instead it
>    holds a set of instructions to produce such an object.
>    (e.g. Reader, State).
> Naturally, it's hard to illustrate nested closures, higher-order
> functions, and objects that aren't really there.  It's easy to
> illustrate a sequential scheme where a single "thing" passes through a
> series of operations, while some related data travels in parallel.
>                    m1 >>= f1 >>= f2 >>= f3        [Eq2]
> In any case, the extreme similarity between desugared "do" and
> desugared "let" leads me to think of the concepts of a manual
> plumbing system and a monadic plumbing system.
> Basically, a manual plumbing system is what I have if I'm threading
> information down through a series of nested function calls in a
> certain stereotypical way.  A monadic plumbing system is what I get
> when I introduce the appropriate monad to encapsulate my threading.
> In fact, if I look at Wadler [*], there are three examples of an
> evaluator that use what I'm calling "manual plumbing".  In section
> 2.5, the operations required of a monad (return, bind) pretty much
> just drop right out.  Wadler even points out the similarity between
> "bind" and "let".
> Now that I finally "get it", I feel that the Wadler paper, section 2.5
> in particular, is probably a better introduction than many of the
> monad tutorials out there.  Moreover, I feel that for /some/ of
> the tutorials out there, they spend too much time and too many
> illustrations explaining things like [Eq2], and then they quickly
> present do-notation and gloss over [Eq1].
> For me, I found that that the concepts of "manual plumbing" and
> "monadic plumbing" were key to actually grasping the Wadler paper and
> understanding what monads are.  In particular, I feel that these two
> concepts might be a way to help other beginners catch on as well.
> OK, so before I attempt to write a monad tutorial based on "manual
> plumbing" and "monadic plumbing", I would like to know, does anyone
> else think this is a good idea?

Why should I recommend a beginner to this tutorial rather than one of
the dozens of others online or, better yet, to Wadler's papers directly
(which is what I do)?

More information about the Haskell-Cafe mailing list