Commit f6a41315 authored by dsf's avatar dsf Committed by chessai

add tryError, withError, handleError, mapError (#60) (#66)

* Control.Monad.Error.Class: add tryError, withError, handleError, mapError (resolves #60)
parent 5de98c26
Unreleased
----------
* `Control.Monad.Cont` now re-exports `evalCont` and `evalContT`
* Add `tryError`, `withError`, `handleError`, and `mapError` to
`Control.Monad.Error.Class`, and re-export from `Control.Monad.Except`.
2.2.2
-----
......
......@@ -42,8 +42,13 @@ module Control.Monad.Error.Class (
Error(..),
MonadError(..),
liftEither,
tryError,
withError,
handleError,
mapError,
) where
import qualified Control.Exception
import Control.Monad.Trans.Except (Except, ExceptT)
import Control.Monad.Trans.Error (Error(..), ErrorT)
import qualified Control.Monad.Trans.Except as ExceptT (throwE, catchE)
......@@ -68,7 +73,7 @@ import Control.Monad.Instances ()
#endif
import Data.Monoid
import Prelude (Either(..), Maybe(..), either, (.), IO)
import Prelude (Either(..), Maybe(..), either, flip, (.), IO)
{- |
The strategy of combining computations that can throw exceptions
......@@ -190,3 +195,25 @@ instance (Monoid w, MonadError e m) => MonadError e (LazyWriter.WriterT w m) whe
instance (Monoid w, MonadError e m) => MonadError e (StrictWriter.WriterT w m) where
throwError = lift . throwError
catchError = StrictWriter.liftCatch catchError
-- | 'MonadError' analogue to the 'Control.Exception.try' function.
tryError :: MonadError e m => m a -> m (Either e a)
tryError action = (liftM Right action) `catchError` (return . Left)
-- | 'MonadError' analogue to the 'withExceptT' function.
-- Modify the value (but not the type) of an error. The type is
-- fixed because of the functional dependency @m -> e@. If you need
-- to change the type of @e@ use 'mapError'.
withError :: MonadError e m => (e -> e) -> m a -> m a
withError f action = tryError action >>= either (throwError . f) return
-- | As 'handle' is flipped 'Control.Exception.catch', 'handleError'
-- is flipped 'catchError'.
handleError :: MonadError e m => (e -> m a) -> m a -> m a
handleError = flip catchError
-- | 'MonadError' analogue of the 'mapExceptT' function. The
-- computation is unwrapped, a function is applied to the @Either@, and
-- the result is lifted into the second 'MonadError' instance.
mapError :: (MonadError e m, MonadError e' n) => (m (Either e a) -> n (Either e' b)) -> m a -> n b
mapError f action = f (tryError action) >>= liftEither
......@@ -38,6 +38,11 @@ module Control.Monad.Except
-- * Monads with error handling
MonadError(..),
liftEither,
tryError,
withError,
handleError,
mapError,
-- * The ExceptT monad transformer
ExceptT(ExceptT),
Except,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment