The definition "Monads are just monoids in the category of endofunctors.", which although true is a bad place to start. It's from a blog post that was largely intended to be a joke. But if you are interested in the correspondence it can be demonstrated in Haskell:
The laymen description of a category is an abstract collection of objects and morphisms between objects. Mappings between categories are called functors and map objects to objects and morphisms to morphisms associatively and preserves identities. An endofunctor is a functor from a category to itself.
{-# LANGUAGE MultiParamTypeClasses,
ConstraintKinds,
FlexibleInstances,
FlexibleContexts #-}
class Category c where
id :: c x x
(.) :: c y z -> c x y -> c x z
class (Category c, Category d) => Functor c d t where
fmap :: c a b -> d (t a) (t b)
type Endofunctor c f = Functor c c f
Mappings between functors which satisfy the so called naturality conditions are called natural transformations. In Haskell these are polymorphic functions of type: (Functor f, Functor g) => forall a. f a -> g a
.
A monad on a category C
is three things (T,η,μ)
, T
is endofunctor and 1
is the identity functor on C
. Mu and eta are two natural transformations that satisfy a triangle identity and an associativity identity, and are defined as:
In Haskell μ
is join
and η
is return
return :: Monad m => a -> m a
join :: Monad m => m (m a) -> m a
A categorical definition of Monad in Haskell could be written:
class (Endofunctor c t) => Monad c t where
eta :: c a (t a)
mu :: c (t (t a)) (t a)
The bind operator can be derived from these.
(>>=) :: (Monad c t) => c a (t b) -> c (t a) (t b)
(>>=) f = mu . fmap f
This is a complete definition, but equivalently you can also show that the Monad laws can be expressed as Monoid laws with a functor category. We can construct this functor category which is a category with objects as functors ( i.e. mappings between categories) and natural transformations (i.e. mappings between functors) as morphisms. In a category of endofunctors all functors are functors between the same category.
newtype CatFunctor c t a b = CatFunctor (c (t a) (t b))
We can show this gives rise to a category with functor composition as morphism composition:
-- Note needs UndecidableInstances to typecheck
instance (Endofunctor c t) => Category (CatFunctor c t) where
id = CatFunctor id
(CatFunctor g) . (CatFunctor f) = CatFunctor (g . f)
The monoid has the usual definition:
class Monoid m where
unit :: m
mult :: m -> m -> m
A monoid over a category of functors has a natural transformations as identity a and a multiplication operation which combines natural transformations. Kleisli composition can be defined to satisfy the multiplication law.
(<=<) :: (Monad c t) => c y (t z) -> c x (t y) -> c x (t z)
f <=< g = mu . fmap f . g
And so you have it "Monads are just monoids in the category of endofunctors" which is just a "pointfree" version of the normal definition of monads from endofunctors and (mu, eta).
instance (Monad c t) => Monoid (c a (t a)) where
unit = eta
mult = (<=<)
With a bit of substitution one can show that the monoidal properties of (<=<)
Are equivalent statement of the triangle and associativity diagrams for the monad's natural transformations.
f <=< unit == f
unit <=< f == f
f <=< (g <=< h) == (f <=< g) <=< h
If you're interested in diagrammatic representations I have written a bit about representing them with string diagrams.