Because we must catch exceptions in the IO monad, if we try to use them inside a monad, or in a stack of monad transformers, we’ll get bounced out to the IO monad. This is almost never what we would actually like.
We defined a MaybeT transformer in Understanding Monad Transformers by Building One, but it is more useful as an aid to
understanding than a programming tool. Fortunately, a dedicated—and more
useful—monad transformer already exists: ErrorT, which is
defined in the
transformer lets us add exceptions to a monad, but it uses its own
special exception machinery, separate from that provided the
Control.Exception module. It gives us some interesting
If we stick with the ErrorT interfaces, we can both throw and catch exceptions within this monad.
Following the naming pattern of other
monad transformers, the execution function is named
runErrorT. An uncaught
ErrorT exception will stop propagating upwards when it
runErrorT. We will not
be kicked out to the IO monad.
We control the type that our exceptions will have.
If we use the
throw function from
Control.Exception inside ErrorT (or if we
undefined), we will still be bounced
out to the IO monad.
As with other
the interface that ErrorT provides is defined by a
-- file: ch19/MonadError.hs class (Monad m) => MonadError e m | m -> e where throwError :: e -- error to throw ...