People say monads are an extension of applicative functors, but I don't see that. Let's take an example of applicative functor: (<*>) :: f(a->b) -> f a -> f b
[(+3)] <*> [2,3,4]
Now, I also expect I can do the same thing as monad, it means I can apply 2 parameters: a context contains a function, and another context to get a context. But for monad, I can't. All I need is to write an ugly function like this:
[2,3,4] >>= (\x->[x+3])
Yes, of course, you can say that [(+3)]
is equivalent to [\x->(x+3)]
. But at least, this function is in context.
Finally, I don't see the equivalence or extension here. Monad is a different style and useful in another story.
Sorry for my ignorance.
I think it clarifies the relationship to define
<*>
again, but using a Monad:Giving the same results as
<*>
:or even
Now the presence of the variables
f
anda
and the last line in the definition of>*>
is the key difference between Monad and Applicative. In Applicative, you can onlyreturn
something at the end, whereas in a Monad, you can do whatever you like withf
anda
.Similarities
In Applicative, you could do
Which we could translate into Monad functions as
or more typically,
Difference
In Monad you could do
For example,
Notice that
checkFirst
changed what happened after I typed then
- it returnedNothing
straight away without giving me a chance to type something forgetLine
or to press enter, whereas if I start withq
it carries on to rungetLine
. This ability to change what gets done on the strength of the values is the key difference between Monad and Applicative, but you can see with the>*>
operator that Monad does everything Applicative does. (They both havereturn
, which Applicative callspure
, and they both have(<$>)
orfmap
because they're both Functors.)The closest you can get to writing
checkFirst
in Applicative isWhich works like this:
(Note: you can't tell the difference between
checkFirst
anddon'tCheckFirst
in ghci in windows, because of a Windows ghc bug in getChar.)Summary
Monad is like Applicative but with the ability to completely change what you're doing based on what values there are.
A monad in Haskell is an Applicative plus
join
, i.e. a function to "flatten" the monad,join :: m (m a) -> m a
.The "Applicative application"
<*>
has typef (a -> b) -> f a -> f b
; if you now choose the typeb
to be in the same Functor, i.e.b :: f c
, the type signature specializes to<*> :: f (a -> f c) -> f a -> f (f c)
. When you don't have a monadic structure, you're done here; however, using the monadicjoin
function, you can flatten the result, getting something in the same monad as before (instead of a double stacked monad).If
T
is an instance ofMonad
, then you can make it an instance ofApplicative
like this:liftM
is defined asap
is defined asSo, "monads are an extension of applicative functors" in the sense that any monad can be made into an applicative functor. Indeed, it is widely (not universally) considered a bug in the standard library that class
Monad
does not derive from classApplicative
.