Writing code which can be used in multiple monads requires careful thought about the definitions of each of the monads in which the computation is to be performed. The functions must be implemented using the subset of features common to all of the required monads.
A useful function in this instance is one to convert a value in
the Maybe monad into any instance of the MonadPlus
class:
Code available in exercise4.hs |
---|
-- convert a Maybe value into another monad maybeToMonad :: (MonadPlus m) => Maybe a -> m a maybeToMonad Nothing = mzero maybeToMonad (Just s) = return s |
Note that this function acts like id
when used in the
Maybe monad. Using this function, we can define a version of parent
similar to the definition we used in the List monad:
Code available in exercise4.hs |
---|
parent :: (MonadPlus m) => Sheep -> m Sheep parent s = (maybeToMonad (mother s)) `mplus` (maybeToMonad (father s)) |
Because of the non-backtracking limitation of the Maybe monad, our
definition of the grandparent
function follows the
definition we used with the Maybe monad, but with the addition of the
calls to maybeToMonad
necessary for use in the List monad:
Code available in exercise4.hs |
---|
grandparent :: (MonadPlus m) => Sheep -> m Sheep grandparent s = (maybeToMonad (mother s) >>= parent) `mplus` (maybeToMonad (father s) >>= parent) |