[Haskell-cafe] More powerful error handling
Philippa Cowderoy
flippa at flippac.org
Sun Feb 17 18:00:18 EST 2008
For a while I've been meaning to propose something along the lines of
this class:
class (MonadError m e, MonadError m' e') =>
MonadErrorRelated m e m' e' | m -> e, m' -> e', m e' -> m' where
catch' :: m a -> (e -> m' a) -> m' a
rethrow :: m a -> (e -> e') -> m' a
with an example instance being:
instance (Error e, Error e') =>
MonadErrorRelated (Either e) e (Either e') e' where
catch' (Right v) _ = Right v
catch' (Left e) h = h e
rethrow c ef = catch' c (throw . ef)
(yep, that definition of rethrow would make a sensible default and there's
a default catch' in terms of rethrow too)
The nicest use would be for converting between a more specific error type
and a more general one that handles a wider range of errors - enabling us
to keep tighter track of which errors are possible in a given piece of
code. Bonus points for using it together with polymorphic variants where
rethrow becomes rather trivial.
The following two functions or close variants might also be useful:
catchMaybe :: (MonadError m ()) => Maybe a -> m a
catchMaybe Nothing = throwError ()
catchMaybe (Just a) = return a
catchEither :: (MonadError m e) => Either e a -> m a
catchEither (Left err) = throwError err
catchEither (Right a) = return a
No doubt there are some names that could use tweaking. As far as I'm
concerned you can count me in the camp of people that resent the existing
MonadError instances all requiring an Error instance too, it makes
things messier when you have access to something like this. But I guess
that's because fail is begging for the following definition:
fail = fail -- fail is made of fail
--
flippa at flippac.org
There is no magic bullet. There are, however, plenty of bullets that
magically home in on feet when not used in exactly the right circumstances.
More information about the Haskell-Cafe
mailing list