Reputation: 1143
I am trying to reconcile the Categorical definition of Monad with the other general representations/definitions that I have seen in some other tutorials/books.
Below, I am (perhaps forcefully) trying to bring the two definitions close, please point out the mistakes and provide corrections, where ever required
So Starting with the definition of Monads
Monads are just monoids in the category of endofunctors.
and with a little understanding of endofunctors, I assume a Monad can be written as
((a->b)->Ma->Mb)->((b->c)->Mb->Mc)
The 'Type
' of LHS (Left hand side) is Mb
, and type of RHS is Mc
, so I suppose I can write it as below
Mb-> (b->c)-> Mc, **which is how we define bind**
And here is how I see Monads in the category of endofuctors (which themselves are in Category
C, with 'types
' as objects
)
.
Does any of this makes sense?
Upvotes: 7
Views: 865
Reputation: 397
It seems to me that you omitted important things:
So, a path to understanding the definition is as follows.
An advice. Do not try to express everything in Haskell. It is designed for writing programs, not mathematics. Mathematical notation is more convenient here because you can write composition of functors as “∘” without going into trouble with type checker.
Upvotes: 2
Reputation: 8439
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:
η : 1 → T
μ : T^2 → T
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.
Upvotes: 6
Reputation: 53911
Well um, I think you're a bit off. A monad is an endofunctor, which in Hask (The category of Haskell types) is something with the kind F :: * -> *
with some function that knows how to inject morphisms (functions) into the subcategory of Hask with functions upon F
s as morphisms and F
s as objects, fmap
. What you have there appears to be a natural transformation in Hask.
Examples: Maybe
, Either a
, (,) a
, etc..
Now a monad also must have 2 natural transformations (Functor F, Functor g => F a -> G a
in hask).
n : Identity -> M
u : M^2 -> M
Or in haskell code
n :: Identity a -> M a -- Identity a == a
u :: M (M a) -> M a
which correspond to return
and join
respectively.
Now we have to get to >>=
. What you had as bind was actually just fmap
, what we actually want is m a -> (a -> m b) -> m b
. This is easily defined as
m >>= f = join $ f `fmap` m
Tada! We have monads. Now for this monoid of endofunctors.
A monoid over endofunctors would have a functors as objects and natural transformations as morphisms. The interesting thing is that the product of two endofunctors is their composition. Here's the Haskell code for our new monoid
type (f <+> g) a = f (g a)
class Functor m => Monoid' m where
midentity' :: Identity a -> m a
mappend' :: (m <+> m) a -> m a
This desugars to
midentity' :: a -> m a
mappend' :: m (m a) -> m a
Look familiar?
Upvotes: 10