grisette-0.5.0.0: src/Grisette/Lib/Control/Monad/Except.hs
{-# LANGUAGE Trustworthy #-}
-- |
-- Module : Grisette.Lib.Control.Monad.Except
-- Copyright : (c) Sirui Lu 2021-2024
-- License : BSD-3-Clause (see the LICENSE file)
--
-- Maintainer : siruilu@cs.washington.edu
-- Stability : Experimental
-- Portability : GHC only
module Grisette.Lib.Control.Monad.Except
( -- * mrg* variants for operations in "Control.Monad.Except"
mrgThrowError,
mrgCatchError,
mrgLiftEither,
mrgTryError,
mrgWithError,
mrgHandleError,
mrgMapError,
mrgModifyError,
)
where
import Control.Monad.Except (ExceptT, MonadError (catchError, throwError))
import Grisette.Internal.Core.Data.Class.Mergeable (Mergeable)
import Grisette.Internal.Core.Data.Class.TryMerge (TryMerge, tryMerge)
import Grisette.Lib.Control.Monad (mrgReturn)
import Grisette.Lib.Control.Monad.Trans.Except (mrgRunExceptT)
import Grisette.Lib.Data.Functor (mrgFmap)
-- | 'Control.Monad.Except.throwError' with 'MergingStrategy' knowledge
-- propagation.
mrgThrowError :: (MonadError e m, TryMerge m, Mergeable a) => e -> m a
mrgThrowError = tryMerge . throwError
{-# INLINE mrgThrowError #-}
-- | 'Control.Monad.Except.catchError' with 'MergingStrategy' knowledge
-- propagation.
mrgCatchError ::
(MonadError e m, TryMerge m, Mergeable a) =>
m a ->
(e -> m a) ->
m a
mrgCatchError v handler = tryMerge $ v `catchError` (tryMerge . handler)
{-# INLINE mrgCatchError #-}
-- | 'Control.Monad.Except.liftEither' with 'MergingStrategy' knowledge
-- propagation.
mrgLiftEither ::
(MonadError e m, TryMerge m, Mergeable a, Mergeable e) => Either e a -> m a
mrgLiftEither = either mrgThrowError mrgReturn
{-# INLINE mrgLiftEither #-}
-- | 'Control.Monad.Except.tryError' with 'MergingStrategy' knowledge
-- propagation.
mrgTryError ::
(MonadError e m, TryMerge m, Mergeable a, Mergeable e) =>
m a ->
m (Either e a)
mrgTryError action = (mrgFmap Right action) `mrgCatchError` (mrgReturn . Left)
{-# INLINE mrgTryError #-}
-- | 'Control.Monad.Except.withError' with 'MergingStrategy' knowledge
-- propagation.
mrgWithError ::
(MonadError e m, TryMerge m, Mergeable a, Mergeable e) =>
(e -> e) ->
m a ->
m a
mrgWithError f action =
tryMerge $ mrgTryError action >>= either (mrgThrowError . f) mrgReturn
{-# INLINE mrgWithError #-}
-- | 'Control.Monad.Except.handleError' with 'MergingStrategy' knowledge
-- propagation.
mrgHandleError ::
(MonadError e m, TryMerge m, Mergeable a, Mergeable e) =>
(e -> m a) ->
m a ->
m a
mrgHandleError = flip mrgCatchError
{-# INLINE mrgHandleError #-}
-- | 'Control.Monad.Except.mapError' with 'MergingStrategy' knowledge
-- propagation.
mrgMapError ::
( MonadError e m,
TryMerge m,
MonadError e' n,
TryMerge n,
Mergeable a,
Mergeable b,
Mergeable e,
Mergeable e'
) =>
(m (Either e a) -> n (Either e' b)) ->
m a ->
n b
mrgMapError f action = tryMerge (f (mrgTryError action)) >>= mrgLiftEither
{-# INLINE mrgMapError #-}
-- | 'Control.Monad.Except.modifyError' with 'MergingStrategy' knowledge
-- propagation.
mrgModifyError ::
( MonadError e' m,
TryMerge m,
Mergeable a,
Mergeable e,
Mergeable e
) =>
(e -> e') ->
ExceptT e m a ->
m a
mrgModifyError f m =
tryMerge $ mrgRunExceptT m >>= either (mrgThrowError . f) mrgReturn
{-# INLINE mrgModifyError #-}