{-# LANGUAGE Trustworthy #-}

-- |
-- Module      :   Grisette.Lib.Control.Monad.Trans.Except
-- Copyright   :   (c) Sirui Lu 2024
-- License     :   BSD-3-Clause (see the LICENSE file)
--
-- Maintainer  :   siruilu@cs.washington.edu
-- Stability   :   Experimental
-- Portability :   GHC only
module Grisette.Lib.Control.Monad.Trans.Except
  ( mrgExcept,
    mrgRunExceptT,
    mrgWithExceptT,
    mrgThrowE,
    mrgCatchE,
  )
where

import Control.Monad.Trans.Except
  ( ExceptT,
    catchE,
    except,
    runExceptT,
    throwE,
    withExceptT,
  )
import Grisette.Internal.Core.Data.Class.Mergeable (Mergeable)
import Grisette.Internal.Core.Data.Class.TryMerge (MonadTryMerge, tryMerge)

-- | 'Control.Monad.Trans.Except.except' with 'MergingStrategy' knowledge
-- propagation.
mrgExcept ::
  (MonadTryMerge m, Mergeable e, Mergeable a) => Either e a -> ExceptT e m a
mrgExcept :: forall (m :: * -> *) e a.
(MonadTryMerge m, Mergeable e, Mergeable a) =>
Either e a -> ExceptT e m a
mrgExcept = ExceptT e m a -> ExceptT e m a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (ExceptT e m a -> ExceptT e m a)
-> (Either e a -> ExceptT e m a) -> Either e a -> ExceptT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Either e a -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => Either e a -> ExceptT e m a
except
{-# INLINE mrgExcept #-}

-- | 'Control.Monad.Trans.Except.runExceptT' with 'MergingStrategy' knowledge
-- propagation.
mrgRunExceptT ::
  (MonadTryMerge m, Mergeable e, Mergeable a) => ExceptT e m a -> m (Either e a)
mrgRunExceptT :: forall (m :: * -> *) e a.
(MonadTryMerge m, Mergeable e, Mergeable a) =>
ExceptT e m a -> m (Either e a)
mrgRunExceptT = m (Either e a) -> m (Either e a)
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (m (Either e a) -> m (Either e a))
-> (ExceptT e m a -> m (Either e a))
-> ExceptT e m a
-> m (Either e a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExceptT e m a -> m (Either e a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT
{-# INLINE mrgRunExceptT #-}

-- | 'Control.Monad.Trans.Except.withExceptT' with 'MergingStrategy' knowledge
-- propagation.
mrgWithExceptT ::
  (MonadTryMerge m, Mergeable a, Mergeable e, Mergeable e') =>
  (e -> e') ->
  ExceptT e m a ->
  ExceptT e' m a
mrgWithExceptT :: forall (m :: * -> *) a e e'.
(MonadTryMerge m, Mergeable a, Mergeable e, Mergeable e') =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
mrgWithExceptT e -> e'
f ExceptT e m a
e = ExceptT e' m a -> ExceptT e' m a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (ExceptT e' m a -> ExceptT e' m a)
-> ExceptT e' m a -> ExceptT e' m a
forall a b. (a -> b) -> a -> b
$ (e -> e') -> ExceptT e m a -> ExceptT e' m a
forall (m :: * -> *) e e' a.
Functor m =>
(e -> e') -> ExceptT e m a -> ExceptT e' m a
withExceptT e -> e'
f (ExceptT e m a -> ExceptT e m a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge ExceptT e m a
e)
{-# INLINE mrgWithExceptT #-}

-- | 'Control.Monad.Trans.Except.throwE' with 'MergingStrategy' knowledge
-- propagation.
mrgThrowE :: (MonadTryMerge m, Mergeable e, Mergeable a) => e -> ExceptT e m a
mrgThrowE :: forall (m :: * -> *) e a.
(MonadTryMerge m, Mergeable e, Mergeable a) =>
e -> ExceptT e m a
mrgThrowE = ExceptT e m a -> ExceptT e m a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (ExceptT e m a -> ExceptT e m a)
-> (e -> ExceptT e m a) -> e -> ExceptT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> ExceptT e m a
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE
{-# INLINE mrgThrowE #-}

-- | 'Control.Monad.Trans.Except.catchE' with 'MergingStrategy' knowledge
-- propagation.
mrgCatchE ::
  (MonadTryMerge m, Mergeable e, Mergeable a) =>
  ExceptT e m a ->
  (e -> ExceptT e m a) ->
  ExceptT e m a
mrgCatchE :: forall (m :: * -> *) e a.
(MonadTryMerge m, Mergeable e, Mergeable a) =>
ExceptT e m a -> (e -> ExceptT e m a) -> ExceptT e m a
mrgCatchE ExceptT e m a
value e -> ExceptT e m a
handler =
  ExceptT e m a -> ExceptT e m a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (ExceptT e m a -> ExceptT e m a) -> ExceptT e m a -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ ExceptT e m a -> (e -> ExceptT e m a) -> ExceptT e m a
forall (m :: * -> *) e a e'.
Monad m =>
ExceptT e m a -> (e -> ExceptT e' m a) -> ExceptT e' m a
catchE (ExceptT e m a -> ExceptT e m a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge ExceptT e m a
value) (ExceptT e m a -> ExceptT e m a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (ExceptT e m a -> ExceptT e m a)
-> (e -> ExceptT e m a) -> e -> ExceptT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> ExceptT e m a
handler)
{-# INLINE mrgCatchE #-}