| This article definitely shows its age. These are the kinds of criticisms the Haskell community has been working quite obsessively to counter for some time. Thus the emphasis on explaining monads in a friendly matter and impressive optimization work that's been put into place. --- And yeah, monads are much more about a particular type of composition or sequencing. Compare the common composition types (warning, scary but harmless jargon to follow) class Monoid m where
e :: m
(<>) :: m -> m -> m
class Functor f => Applicative f where
pure :: a -> f a
ap :: f (a -> b) -> f a -> f b
class Functor f => Monoidal f where -- isomorphic to Applicative
unit :: f ()
prod :: (f a, f b) -> f (a, b)
class Applicative m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
class Applicative m => Monad' m where -- isomorphic to Monad
return :: a -> m a
bind :: m a -> (a -> m b) -> m b
class Profunctor f => Arrow f where
arr :: (a -> b) -> f a b
(>>>) :: f a b -> f b c -> f a c
-- kind of ignore this one :)
first :: f a b -> f (a, c) (b, c)
You can see a progression in the constraints on how things combine as you move down the list. First you have plain composition of non-container Functor types.Then you have the Applicative/Monoidal functors (they're equivalent/isomorphic) which are probably most clearly demonstrated by the Monoidal class--it implements composition of Functors which maps to products in the contained types (or, has a "applicative" product which commutes with the functor)! Then you have Monadic functor composition where you have "sequential" or "inward" composition via join (compare to Applicative's "horizontal" product composition) which can be implemented by the 'bind' function which maps a function that rewraps contained values. Finally you have the Arrow types which add composition to Profunctors (which are like functors which contain both "incoming" and "outgoing" values) by composing them like a category. --- Which is a lot of words to say that (1) Monads are just one of a whole group of "kinds" of composition and (2) they basically represent composition which allows for control over how functorial contexts get sequenced. |