Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

So this is going to sound snarky and/or stupid at first, but: Monads are functors with a 'join' ("flatten") operation.

A functor is a type parameterized by another type[1], say 'a', with a function 'fmap' taking a function 'a -> b', yielding the original object except that its type is now parameterized by 'b'[2]. A monad's 'join' operation takes 'f (f a)' onto 'f a'.

On top of this, there are certain laws which must be obeyed. The functor laws amount to saying that 'fmap' can't change anything about the object (including structure) which doesn't depend on the parameter 'a', but must change everything which does depend on 'a'. The monad laws amount to saying that 'join' has a certain associative structure[3], and also that there is a left- and right-identity 'return: a -> f a'.

[1] a la Java generics, for those not into FP

[2] i.e., fmap has type 'forall a b. (a -> b) -> (f a -> f b)'

[3] Explaining exactly what this associative structure is in these terms is tricky, since 'join' as described is unary. Here's where you have to introduce the function 'bind', '(\f -> join . fmap f)': 'bind g . bind f' === 'bind (bind g . f)'. But it's really not essential; the most intuitive consequence is that Haskell's 'do' notation works like you want it to.



You need "return" too. Can't get that from merely being a functor.


> and also that there is a left- and right-identity 'return: a -> f a'

RTF, uh, Comment.

The point being that I think it's best to understand return in the context of the more important operation join. You might wonder, "well why don't functors have a generic constructor", and (among other answers to that) the reason is that it doesn't serve any purpose in the functor laws. But return does serve a purpose for the monad laws, namely, being an identity of sorts.




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

Search: