What is a monad in FP, in categorical terms?
Every time someone promises to "explain monads", my interest is piqued, only to be replaced by frustration when the alleged "explanation" is a long list of examples terminated by some off-hand remark that the "mathematical theory" behind the "esoteric ideas" is "too complicated to explain at this point".
Now I'm asking for the opposite. I have a solid grasp on category theory and I'm not afraid of diagram chasing, Yoneda's lemma or derived functors (and indeed on monads and adjunctions in the categorical sense).
Could someone give me a clear and concise definition of what a monad is in functional programming? The fewer examples the better: sometimes one clear concept says more than a hundred timid examples. Haskell would do nicely as a language for demonstration though I'm not picky.
Solution 1:
This question has some good answers: Monads as adjunctions
More to the point, Derek Elkins' "Calculating Monads with Category Theory" article in TMR #13 should have the sort of constructions you're looking for: http://www.haskell.org/wikiupload/8/85/TMR-Issue13.pdf
Finally, and perhaps this is really the closest to what you're looking for, you can go straight to the source and look at Moggi's seminal papers on the topic from 1988-91: http://www.disi.unige.it/person/MoggiE/publications.html
See in particular "Notions of computation and monads".
My own I'm sure too condensed/imprecise take:
Begin with a category Hask
whose objects are Haskell types, and whose morphisms are functions. Functions are also objects in Hask
, as are products. So Hask
is Cartesian closed. Now introduce an arrow mapping every object in Hask
to MHask
which is a subset of the objects in Hask
. Unit!
Next introduce an arrow mapping every arrow on Hask
to an arrow on MHask
. This gives us map, and makes MHask
a covariant endofunctor. Now introduce an arrow mapping every object in MHask
which is generated from an object in MHask
(via unit) to the object in MHask
which generates it. Join! And from the that, MHask
is a monad (and a monoidal endofunctor to be more precise).
I'm sure there is a reason why the above is deficient, which is why I'd really direct you, if you're looking for formalism, to the Moggi papers in particular.
Solution 2:
As a compliment to Carl's answer, a Monad in Haskell is (theoretically) this:
class Monad m where
join :: m (m a) -> m a
return :: a -> m a
fmap :: (a -> b) -> m a -> m b
Note that "bind" (>>=
) can be defined as
x >>= f = join (fmap f x)
According to the Haskell Wiki
A monad in a category C is a triple (F : C → C, η : Id → F, μ : F ∘ F → F)
...with some axioms. For Haskell, fmap
, return
, and join
line up with F, η, and μ, respectively. (fmap
in Haskell defines a Functor). If I'm not mistaken, Scala calls these map
, pure
, and join
respectively. (Scala calls bind "flatMap")