Solution (source code)

= Solution

There is one undifferentiated exception, so use the two alternatives of the <Haskell> <algebraic data type> `Maybe`: `Just x` succeeds and `Nothing` fails. A suitable <exception monad transformer> is:

``
type ExT m a = m (Maybe a)

result :: Monad m => a -> ExT m a
result x = resultM (Just x)

bind :: Monad m => ExT m a -> (a -> ExT m b) -> ExT m b
bind p f = bindM p (\r -> case r of
  Nothing -> resultM Nothing
  Just x  -> f x)

orelse :: Monad m => ExT m a -> ExT m a -> ExT m a
orelse p q = bindM p (\r -> case r of
  Nothing -> q
  Just x  -> resultM (Just x))

failure :: Monad m => ExT m a
failure = resultM Nothing
``

The distinction between `bindM` and `bind` matters. The handler must inspect the failed alternative using the base <computational monad>; the transformed `bind` would propagate failure without running that inspection. The alternative computation `q` runs only after `p` returns `Nothing`; any effects already performed by the base <computational monad> remain subject to that base's semantics.

Left identity follows by selecting `Just x`. Right identity follows because either alternative is passed back to `resultM`. For <associativity>, base <associativity> exposes the first alternative: `Nothing` propagates through both remaining steps; `Just x` runs `f x`, with its `Nothing` and `Just` alternatives treated identically on both sides. Thus this representation also satisfies the <monad laws>.
$$
\boxed{\operatorname{ExT}\ m\ A=m(\operatorname{Maybe}\ A),\qquad
\operatorname{failure}\mathbin{\operatorname{orelse}}q=q,\qquad
\operatorname{result}(x)\mathbin{\operatorname{orelse}}q=\operatorname{result}(x).}
$$