
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? [*] "Monads for Functional Programming". (http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf)

On 7 Jun 2008, at 08:05, Ronald Guida wrote:
What made monads "click" for me is when I understood the following things:
Well, in case anybody's interested, I didn't know anything about monads before I tried to read the book "Toposes theory" (not sure about the exact name, I've read it in Russian) by P.T. Johnstone. It's Chapter 0 contained some facts about monads without proofs or even definitions. I've looked for some definitions in Mathematical Encyclopedia, asked one of my professors about other ones, tried to prove all results in this chapter by myself (successfully), and, suddenly, found out that I understand what monads are. Then, while reading YAHT, I've thought a bit, then realized, that Haskell monads are the same beast I already know (I didn't know about Kleisli triples before), and everything was clear.

On Saturday 07 June 2008, Ronald Guida wrote:
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)))
In fact, this is the identity monad (this is not valid Haskell, but we'll let that slide): type Id a = a instance Monad Id where return a = a a >>= f = f a do x1 <- f1 f1 >>= \x1 (\x1 -> x2 <- f2 f2 >>= \x2 (\x2 -> x3 <- f3 f3 >>= \x3 (\x3 -> f x1 x2 x3) f3) return (f x1 x2 x3) return (f x1 x2 x3) f2) f1 Which is the same as the lets modulo let-polymorphism and recursive bindings. (In Haskell, you need a newtype wrapper but it's otherwise the same.)
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?
I think the general consensus is "don't write yet more monad tutorials." If you think Wadler's original paper is good, then it doesn't hurt to recommend it (you could instead write a "don't be afraid of reading academic papers" tutorial :)). But don't let me stop you, of course. :) -- Dan

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)?
participants (4)
-
Dan Doel
-
Derek Elkins
-
Miguel Mitrofanov
-
Ronald Guida