First of all, there are two levels: types and values. As objects of Hask are types, you can map them only with type constructors, which have the * -> *
kind:
α -> F α
(for Functor F
),
β -> M β
(for Monad M
).
Then for a functor you need a map on morphisms (i.e. functions, which are values): it's just fmap :: (α -> β) -> (F α -> F β)
.
So far, I guess, I'm not saying anything new. But important thing is that return :: α -> M α
of Monad
is not a mapper of a type α
to the M α
as you may think. Regarding to the math definition of a monad, return
corresponds to a natural transformation from Id
functor to the M
functor. Just that this Id
functor is kind of implicit. The standard definition of monad requires also another natural transformation M ? M -> M
. So translating it to Haskell would be like
class Functor m => Monad m where
return :: Id α -> m α
join :: m (m α) -> m α
(As a side-note: these two natural transformations are actually the unit and multiplication, which make monad a monoid in the category of endofunctors)
The actual definition differs but is equivalent. See Haskell/wiki on that.
If you take the composition-like operator derived form the standard bind >>= :: m α -> (α -> m β) -> m β
:
(>=>) :: Monad m => (α -> m β) -> (β -> m γ) -> (α -> m γ)
f >=> g = a => f a >>= g
you can see, that it's all actually about the Kleisli category. See also the article on nLab about monads in computer science.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…