This is a general question, not tied to any one piece of code.
Say you have a type T a
that can be given an instance of Monad
. Since every mona
I think you mis-understand how sub-classes work in Haskell. They aren't like OO sub-classes! Instead, a sub-class constraint, like
class Applicative m => Monad m
says "any type with a canonical Monad
structure must also have a canonical Applicative
structure". There are two basic reasons why you would place a constraint like that:
For example, consider:
class Vector v where
(.^) :: Double -> v -> v
(+^) :: v -> v -> v
negateV :: v -> v
class Metric a where
distance :: a -> a -> Double
class (Vector v, Metric v) => Norm v where
norm :: v -> Double
The first super-class constraint on Norm
arises because the concept of a normed space is really weak unless you also assume a vector space structure; the second arises because (given a vector space) a Norm
induces a Metric
, which you can prove by observing that
instance Metric V where
distance v0 v1 = norm (v0 .^ negateV v1)
is a valid Metric
instance for any V
with a valid Vector
instance and a valid norm
function. We say that the norm induces a metric. See http://en.wikipedia.org/wiki/Normed_vector_space#Topological_structure .
The Functor
and Applicative
super-classes on Monad
are like Metric
, not like Vector
: the return
and >>=
functions from Monad
induce Functor
and Applicative
structures:
fmap
: can be defined as fmap f a = a >>= return . f
, which was liftM
in the Haskell 98 standard library.pure
: is the same operation as return
; the two names is a legacy from when Applicative
wasn't a super-class of Monad
.<*>
: can be defined as af <*> ax = af >>= \ f -> ax >>= \ x -> return (f x)
, which was liftM2 ($)
in the Haskell 98 standard library.join
: can be defined as join aa = aa >>= id
.So it's perfectly sensible, mathematically, to define the Functor
and Applicative
operations in terms of Monad
.