Solution to Exercise 2

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)

Return to exercises.