The two choices for a parent are the mother and the father, suggesting
a straightforward implementation of the parent function
using the mplus operator:
| Code available in exercise2.hs |
|---|
parent :: Sheep -> Maybe Sheep parent s = (mother s) `mplus` (father s) |
In this case, the mplus operator is used to combine the
values from the monadic functions mother and
father.
The grandparent function is a little trickier. You might
be tempted to simply write:
grandparent s = do p <- parent s
parent p
|
but this is not correct. To see why not, you must remember that
the mplus operator in the Maybe monad
returns its first argument unless it is Nothing, in
which case it returns its second argument. Imagine what would happen
if the sheep had a mother without parents but a father with parents.
Then p would be the mother and parent p
would be Nothing, even though there are grandparents on
the father's side.
The problem is that there is no back-tracking
facility in the Maybe monad's strategy for mplus.
We can get around this by carefully defining the
grandparent function so that no backtracking is required:
| Code available in exercise2.hs |
|---|
grandparent :: Sheep -> Maybe Sheep grandparent s = (mother s >>= parent) `mplus` (father s >>= parent) |