{-# LANGUAGE Trustworthy #-}

-- |
-- Module      :   Grisette.Lib.Control.Monad.Except
-- Copyright   :   (c) Sirui Lu 2021-2023
-- 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,
  )
where

import Control.Monad.Except
import Grisette.Core.Control.Monad.Union
import Grisette.Core.Data.Class.Bool
import Grisette.Core.Data.Class.Mergeable
import Grisette.Core.Data.Class.SimpleMergeable

-- | 'throwError' with 'MergingStrategy' knowledge propagation.
mrgThrowError :: (MonadError e m, MonadUnion m, Mergeable a) => e -> m a
mrgThrowError :: forall e (m :: * -> *) a.
(MonadError e m, MonadUnion m, Mergeable a) =>
e -> m a
mrgThrowError = forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError
{-# INLINE mrgThrowError #-}

-- | 'catchError' with 'MergingStrategy' knowledge propagation.
mrgCatchError ::
  (MonadError e m, MonadUnion m, Mergeable a) =>
  m a ->
  (e -> m a) ->
  m a
mrgCatchError :: forall e (m :: * -> *) a.
(MonadError e m, MonadUnion m, Mergeable a) =>
m a -> (e -> m a) -> m a
mrgCatchError m a
v e -> m a
handler = forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge forall a b. (a -> b) -> a -> b
$ m a
v forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` (forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> m a
handler)
{-# INLINE mrgCatchError #-}