Some examples and non-examples of monads.
Examples
Lists
Linked lists form what can be loosely thought of as a nondeterminism monad. In
fact, join
is simply concat
and >>=
is an infix version of concatMap
.
Functions
Functions from a fixed value form a monad. join
can be used to pass the same
argument to a function twice, while return
is a synonym for const
. I do not
know of any interpretation of >>=
, but note that fmap
is (.)
.
As an example, we can define the following:
import Control.Arrow
import Control.Monad
both :: (a -> a) -> (a, a) -> (a, a)
both = join (***)
which is equivalent to
both :: (a -> a) -> (a, a) -> (a, a)
both f (x, y) = (f x, f y)
Note also that sequence
can be used to apply a list of functions to a common
value, as follows:
λ:> sequence [(+1), (+2)] 3
[4,5]
Finally, note that (<*>)
allows us to split inputs to a function, as in the
following:
idempotent :: Eq a => (a -> a) -> a -> Bool
idempotent = ((==) <*>)
which is equivalent to the slightly clearer
idempotent :: Eq a => (a -> a) -> a -> Bool
idempotent f x = x == f x
IO
The IO
monad is especially important because it allows relatively
painless side-effecting computation in a lazy language. In Haskell, it is
defined as follows:
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
This is essentially a state monad with state type State# RealWorld
.
Non-Examples
Tuples
Tuples are functorial, but not monadic. To see why this is the case, consider the type signature of a hypothetical monad instance:
join :: (a, (a, b)) -> (a, b)
join (x, (y, z)) = ???
Such a function would be immoral as it must either forget x
or y
with no
reason to prefer one over the other. Worse, consider return
:
return :: a -> (b, a)
return = ???
This would require undefined
to work in general.
Constant Functor
The constant functor is a functor, but not an applicative functor. A hypothetical applicative instance would have the following type signature:
(<*>) :: Constant a (b -> c) -> Constant a b -> Constant b c
(<*>) (Constant x) (Constant y) = ???
This would be immoral; similar problems arise for pure
as above with return
and tuples.