Some examples and non-examples of monads.
Linked lists form what can be loosely thought of as a nondeterminism monad. In
join is simply
>>= is an infix version of
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
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
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 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
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
y with no
reason to prefer one over the other. Worse, consider
return :: a -> (b, a) return = ???
This would require
undefined to work in general.
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