Haskell allows to define a new type around another one, thus creating a
"type with context".
Hence, one may differentiate (Int, Int)
in cases such as
data Time = Time (Int, Int)
--(h:m) and data Coord = Coord (Int, Int)
--(x,y).
These new types will have related functions knowing that the wrapped "base" type is effectively an Int
.
One step further, is to create "generic" types, by using "type parameters" in the data
clause, as in the famous monad: data Maybe t = Nothing | Just t
.
These kind of generic types are going to be used by wide range of functions, and for
addressing many different needs, namely: exception: Maybe, global state: State, input/output: IO, nondeterminism: [], environment: Reader, logger: Writer.
Here arises the convenience of having two functions: return :: a -> m a
for building a context around type a
, and (>>=) :: m a -> (a -> m b) -> m b
for automatically having a function m a -> m b
based on an previous a -> m b
. This is summarized by the monad class:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
so that new generic types have to define what means return
and >>=
for them to be an instance of Monad
.
It seems to me that this is going to happen for every generic type, so the concrete questions are:
- Every generic type
data MyThing t = ...
must be and instance of Monad? - At least in general, is it convenient that Every generic type
data MyThing t = ...
is an instance of Monad? - Is any case where a generic type
data MyThing t = ...
must not be an instance of Monad? (apart from trivial cases). Why? - Is it interesting that even a concrete context type,
data Time = Time (Int, Int)
, is a Monad?
Examples, corrections and edits of the above explanation are welcome and desired.
Thanks.