Hacker News new | past | comments | ask | show | jobs | submit login
Monad is not difficult (ianen.org)
28 points by jmillikin on Feb 24, 2010 | hide | past | favorite | 20 comments



Honestly, I don't think your explanation is any easier to grasp than "All about monads". I think RWH and the Typeclassopedia are easier for the uninitiated to understand. ("You could have invented monads" is also very good. Although I think it's sad that I know the exact titles of blog posts about monads...)

What I like about RWH is that it builds up monads as "why you need this". You see code in its non-monadic form for a while, and then monads are introduced, and suddenly you see the same program being significantly smaller. You understand the before and after, and can begin to reason for yourself what a monad is. And it becomes abundantly clear why they are useful in Haskell -- you just saw your program shrink by 2/3s.

And a nitpick unrelated to your article -- I notice a lot of Haskell articles implement things unnaturally just to use a certain feature. This makes it hard to understand why you would actually want to use that feature. The reader skims the article, says "this is just a fold", and dismisses monads forever. (I remember reading LYAH's section on applicative functors once. All the examples do nothing, they are merely functions that technically type-check. Not a good way to learn; the real paper on applicative functors is much more approachable. But I digress.)


I agree, generally; it's a bit hard to write something better than RWH over a lunch break. But sometimes, breaking down the same problem from multiple viewpoints helps readers to understand what's going on.

My particular purpose in writing this is to demystify monads specifically, especially for people who are casually interested in learning Haskell but unwilling to read a few hundred pages on it. RWH is great, but it doesn't explain monads until chapter 14 -- that's a lot of material a reader has to understand before they can even parse the examples.


But sometimes, breaking down the same problem from multiple viewpoints helps readers to understand what's going on.

I think 43% of the confusion about monads is due to the sheer number of "monad tutorials", each explaining two or three functions (return/bind, pure/fmap/join) with different, overly-complex analogies. (A monad is like a burrito, a monad is like a space suit, a monad is like a nuclear waste container...)

The tutorials start with some analogy, and then inevitably explain how "the list monad" and "the maybe monad" work. At the end you know that monads are like burritos, how to apply a function to every value in a list, and how to return failure from a function. But you still don't know anything about monads, or more importantly why monads.

If I were to write a monad tutorial, it would include these key points:

1) A monad is not a thing, it's a property of other things. Maybe is a thing. A list is a thing. Both are monads. (My bike is a thing. My wall is a thing. Both are blue.)

2) The abstract concept of a monad lets you reuse code. If you want to apply a function to every value of a list, you could do that without monads. If you want functions to be able to fail, and you want the failures to be composable, you could do that without monads. But what you can't do without monads is write a function like liftM2. With monads, you can turn a normal function into one that works on lists. Or that works on IO. Or that works on computations that can fail. You get to use the same function for all three types. That's the point of monads.

(Then there will be a code example:

    2 + 3 --> 5
    liftM2 (+) (Just 2) (Just 3) --> Just 5
    liftM2 (+) Nothing (Just 3) --> Nothing
    liftM2 (+) (Just 2) Nothing --> Nothing
    liftM2 (+) [1,2] [3,4] --> [4,5,5,6]
    liftM2 (+) readLn readLn --> 1 <ENT> 2 <ENT> --> 3
Then it all makes sense!)


(note: HN mangles <*>, so I'm using <∗> instead

Isn't #2 a property of functors in general? I know I usually use <$> and <∗> rather than the liftM family because they don't limit the number of parameters.

  (+) <$> (Just 2) <∗> (Just 3)
  (+) <$> [1,2] <∗> [3,4]
  (+) <$> readLn <∗> readLn


Does this mean that you could go on an say:

    (+) <$> (Just 2) <∗> (Just 3) <∗> (Just 5)
And it would have the same meaning as:

    liftM3 (+) (Just 2) (Just 3) (Just 5)

edited for formatting


Exactly. You can use the applicative operators on functions with an arbitrary number of parameters.

Note, though, that (+) only takes two parameters, so your examples won't work as written. These should be equivalent:

  enumFromThenTo <$> Just 2 <*> Just 3 <*> Just 5
  liftM3 enumFromThenTo (Just 2) (Just 3) (Just 5)


Neat. I did see that liftM3 takes a function of 3 arguments, and just plain ignored that fact in my example :)

And to be clear, for <$> and <*>, you need a Functor instance defined for you type right?

Are there benefits to using one or the other, they seem to evaluate the same, is GHC able to optimize Monad and Functor equally?


Right -- liftM and friends are for monads, <$> and <∗> are for functors. All monads are supposed to be functors, though there's currently no type-level guarantee for historical reasons. Most instances of Monad also provide an instance of Functor.

  Are there benefits to using one or the other, they seem to evaluate the same, is GHC able to optimize Monad and Functor equally?
I believe there's currently no special optimizations for either case, though as I don't poke around in GHC this statement may be mistaken.

The primary advantage of the application operators over liftM is that there's no liftM6, liftM7, etc; you can type <∗> as much as you want.


In Haskell, <∗> is implemented in "Applicative", not "Functor". So a Functor instance is not enough. <$> is from Functor, however.


Oh, that's right -- I forgot applicatives are a separate class.

Regardless, the concept of "lifting" pure functions is separate from monads, which exist to enforce sequencing.


Yes.


Agreed. Clear, real examples of abstract ideas are really important, and applies to much more than just monads. RWH's monads stuff (in particular its parsec chapter) is a good example of a concept in action, and its easy to see why you would actually use that model.

Some 'first principles' things are difficult to present like this because there are usually better ways to do it. The state monad is like this. Even in haskell there are more expressive (and easier to use) tools to do the same thing. In this case i think we can all accept somewhat ad hoc examples as long as they are disclaimed.


This is an extension of my comment at < http://news.ycombinator.com/item?id=1144481 > -- it was so well received that I decided to write up a proper article.

There's something about the word "monad" that just scares the hell out of people, but hopefully approaching monads from a more practical and less mathematical standpoint will make grasping them easier. They're really not that complicated.


When I was figuring out what a monad was the biggest impediments were:

1) Superfluous analogies

2) Usage of do-syntax rather than bind and return.

Do-syntax, which sweeps the best example of how a monad _actually_ works under the rug, used in conjunction with the phrase "inside a monad", can cause beginners over-complicate and mysticize the idea of a monad.

I have not yet read the above tutorial, but the best one I have seen to date is http://ertes.de/articles/monads.html


That's an excellent link; I've added it to the introduction.


I think the best way of looking at monads for most programmers is the one described in http://blog.sigfpe.com/2010/01/monads-are-trees-with-graftin... (which links to the actual PDF https://dl.dropbox.com/u/828035/Monads/monads.pdf ).


This site causes a tab crash on Chrome 5.0.307.9 beta running on x64 Linux.


Sorry about that :(

It's valid markup[1], and doesn't use any weird plugins. You may want to report the crash to the Chrome team.

[1] http://validator.w3.org/check?uri=http%3A%2F%2Fianen.org%2Fa...


I did, using a web form I found that required that I tell it what version of Windows I'm using and upload a log file that doesn't seem to exist on the Linux version.

It's an interesting enough article to open another browser though.


I'm pretty sure if someone would try to explain Monads without actually using Haskell syntax it might actually be possible to understand. This explained nothing.

Haskell advocates mention pure code and monads as pros of Haskell and typical Haskell conventions. But I'm simply not willing to learn a language's full syntax to learn about some generic computing concept and how it is employed in a specific language.

If I need to learn the language you are trying to sell me to understand the concept your are trying to explain me in order to sell me the language, don't expect to get very far.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: