Carsten's answer is quite correct, of course, but it is, in my experience, often more intuitive to specify a monad by defining the join
function (especially in this case, where any child will understand that if Mum says that we will perhaps definitely have ice cream tomorrow that means that we will perhaps have ice cream..)
join :: Certainty (Certainty a) -> Certainty a
join Nope = Nope
join (Perhaps Nope) = Nope
join (Perhaps (Perhaps x)) = Perhaps x
join (Perhaps (Definitely x)) = Perhaps x
join (Definitely Nope) = Nope
join (Definitely (Perhaps x)) = Perhaps x
join (Definitely (Definitely x)) = Definitely x
Of course, >>=
can be defined in terms of join
and fmap
(which is trivial for Certainty
, and can be automatically found by ghc
with -XDeriveFunctor
) by
x >>= f = join (fmap f x)
which makes my definition equivalent to Carsten's
Moreover, by looking at the last three lines of the definition of join
we see that for all x :: Certainty a
we have join (Definitely x) = x
which suggests that
return x = Definitely x