If I inspect the kind
of Maybe
I get this:
λ> :k Maybe
Maybe :: * -> *
Now, if I inspect the kind of Monad
I get this:
λ> :k Monad
Monad :: (* -> *) -> Constraint
What is Constraint
there and why it is needed ? Why not just this * -> *
?
Constraint
is the kind of e.g.Show Int
,Monad Maybe
, andMonoid [a]
. Roughly, it is the kind of everything that can occur on the left side of=>
in type annotations.Now since
and
Int
is a type, i.e.we can assign a functional kind to
Show
as followsIn your case it just happens that a
Monad
takes argument likeMaybe
, soUnlike
Maybe
,Monad
is not a type; it is a typeclass.The same goes for other typeclasses:
Where
*
represents concrete types (such asBool
orInt
),->
represent higher-kinded types (such asMaybe
), andConstraint
represents the idea of a type constraint. This is why:As we know we can't make a signature like this:
Because
Monad
should be used as a constraint, to say that, 'this must be a monad to work':We do this because we know that
return
can't work on any old typem
, so we define the behaviour ofreturn
for different types under the nameMonad
. In other words, there is no single thing that can be called a Monad, but only behaviour that can be called Monadic.For this reason, we have created this type constraint, saying that we must have pre-defined something as a Monad to use this function. This is why the kind of
Monad
is(* -> *) -> Constraint
- it itself is not a type!Maybe
is an instance ofMonad
. This means that somewhere, someone has written:...and defined how
Maybe
should behave as a Monad. This is why we can useMaybe
with functions or types that have the prefix constraintMonad m => ...
. This is essentially where one defines the constraint applied byMonad
.