{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Control.Monad.Trans.Either
-- Copyright   :  (C) 2017 Tim McGilchrist
-- License     :  BSD-style (see the file LICENSE)
--
-- Maintainer  :  timmcgil@gmail.com
-- Stability   :  experimental
-- Portability :  portable
--
-- This monad transformer extends "Control.Monad.Trans.Except" with a more
-- familar "Either" naming.
-----------------------------------------------------------------------------
module Control.Monad.Trans.Either (
  -- * Control.Monad.Trans.Either
    EitherT
  , pattern EitherT
  , newEitherT
  , runEitherT
  , eitherT
  , left
  , right
  , mapEitherT
  , hoistEither
  , bimapEitherT

  -- * Extensions
  , firstEitherT
  , secondEitherT
  , hoistMaybe
  , hoistEitherT
  , handleIOEitherT
  , handleEitherT
  , handlesEitherT
  , handleLeftT

  , catchIOEitherT
  , catchEitherT
  , catchesEitherT
  , catchLeftT

  , bracketEitherT
  , bracketExceptionT

  , hushM
  , onLeft
  , onNothing
  ) where

import           Control.Exception (Exception, IOException, SomeException)
import qualified Control.Exception as Exception
import           Control.Monad (Monad (..), (=<<))
import           Control.Monad.Catch (Handler (..), MonadCatch, MonadMask, catchAll, mask, throwM)
import qualified Control.Monad.Catch as Catch
import           Control.Monad.IO.Class (MonadIO, liftIO)
import           Control.Monad.Trans.Class (lift)
import           Control.Monad.Trans.Except (ExceptT (..))

import           Data.Either (Either (..), either)
import           Data.Foldable (Foldable, foldr)
import           Data.Function (const, flip, id, ($), (.))
import           Data.Functor (Functor (..))
import           Data.Maybe (Maybe (..), maybe)

import           System.IO (IO)

------------------------------------------------------------------------
-- Control.Monad.Trans.Either

-- | Type alias for "ExceptT"
--
type EitherT = ExceptT

pattern EitherT :: m (Either x a) -> ExceptT x m a
pattern $bEitherT :: forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
$mEitherT :: forall {r} {m :: * -> *} {x} {a}.
ExceptT x m a -> (m (Either x a) -> r) -> ((# #) -> r) -> r
EitherT m = ExceptT m

-- | Extractor for computations in the either monad.
-- (The inverse of 'newEitherT').
runEitherT :: EitherT x m a -> m (Either x a)
runEitherT :: forall x (m :: * -> *) a. EitherT x m a -> m (Either x a)
runEitherT (ExceptT m (Either x a)
m) = m (Either x a)
m
{-# INLINE runEitherT #-}

-- | Constructor for computations in the either monad.
-- (The inverse of 'runEitherT').
newEitherT :: m (Either x a) -> EitherT x m a
newEitherT :: forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
newEitherT =
  forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT
{-# INLINE newEitherT #-}

-- | Map over both arguments at the same time.
--
-- Specialised version of 'bimap' for 'EitherT'.
eitherT :: Monad m => (x -> m b) -> (a -> m b) -> EitherT x m a -> m b
eitherT :: forall (m :: * -> *) x b a.
Monad m =>
(x -> m b) -> (a -> m b) -> EitherT x m a -> m b
eitherT x -> m b
f a -> m b
g EitherT x m a
m =
  forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either x -> m b
f a -> m b
g forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall x (m :: * -> *) a. EitherT x m a -> m (Either x a)
runEitherT EitherT x m a
m
{-# INLINE eitherT #-}

-- | Constructor for left computations.
left :: Monad m => x -> EitherT x m a
left :: forall (m :: * -> *) x a. Monad m => x -> EitherT x m a
left =
  forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
EitherT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left
{-# INLINE left #-}

-- | Constructor for right computations.
right :: Monad m => a -> EitherT x m a
right :: forall (m :: * -> *) a x. Monad m => a -> EitherT x m a
right =
  forall (m :: * -> *) a. Monad m => a -> m a
return
{-# INLINE right #-}

-- |
mapEitherT :: (m (Either x a) -> n (Either y b)) -> EitherT x m a -> EitherT y n b
mapEitherT :: forall (m :: * -> *) x a (n :: * -> *) y b.
(m (Either x a) -> n (Either y b))
-> EitherT x m a -> EitherT y n b
mapEitherT m (Either x a) -> n (Either y b)
f =
  forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
EitherT forall b c a. (b -> c) -> (a -> b) -> a -> c
. m (Either x a) -> n (Either y b)
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall x (m :: * -> *) a. EitherT x m a -> m (Either x a)
runEitherT
{-# INLINE mapEitherT #-}

-- | Hoist an 'Either' into an 'EitherT' m.
hoistEither :: Monad m => Either x a -> EitherT x m a
hoistEither :: forall (m :: * -> *) x a. Monad m => Either x a -> EitherT x m a
hoistEither =
  forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
EitherT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => a -> m a
return
{-# INLINE hoistEither #-}

-- | Map the unwrapped computation using the given function.
bimapEitherT :: Functor m => (x -> y) -> (a -> b) -> EitherT x m a -> EitherT y m b
bimapEitherT :: forall (m :: * -> *) x y a b.
Functor m =>
(x -> y) -> (a -> b) -> EitherT x m a -> EitherT y m b
bimapEitherT x -> y
f a -> b
g =
  let
    h :: Either x a -> Either y b
h (Left  x
e) = forall a b. a -> Either a b
Left  (x -> y
f x
e)
    h (Right a
a) = forall a b. b -> Either a b
Right (a -> b
g a
a)
  in
    forall (m :: * -> *) x a (n :: * -> *) y b.
(m (Either x a) -> n (Either y b))
-> EitherT x m a -> EitherT y n b
mapEitherT (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either x a -> Either y b
h)
{-# INLINE bimapEitherT #-}

-- | Map the 'Left' unwrapped computation using the given function.
firstEitherT :: Functor m => (x -> y) -> EitherT x m a -> EitherT y m a
firstEitherT :: forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> EitherT x m a -> EitherT y m a
firstEitherT x -> y
f =
  forall (m :: * -> *) x y a b.
Functor m =>
(x -> y) -> (a -> b) -> EitherT x m a -> EitherT y m b
bimapEitherT x -> y
f forall a. a -> a
id
{-# INLINE firstEitherT #-}

-- | Map the 'Right' unwrapped computation using the given function.
secondEitherT :: Functor m => (a -> b) -> EitherT x m a -> EitherT x m b
secondEitherT :: forall (m :: * -> *) a b x.
Functor m =>
(a -> b) -> EitherT x m a -> EitherT x m b
secondEitherT =
  forall (m :: * -> *) x y a b.
Functor m =>
(x -> y) -> (a -> b) -> EitherT x m a -> EitherT y m b
bimapEitherT forall a. a -> a
id
{-# INLINE secondEitherT #-}

-- | Hoist 'Maybe' a into 'Right' a.
hoistMaybe :: Monad m => x -> Maybe a -> EitherT x m a
hoistMaybe :: forall (m :: * -> *) x a. Monad m => x -> Maybe a -> EitherT x m a
hoistMaybe x
x =
  forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) x a. Monad m => x -> EitherT x m a
left x
x) forall (m :: * -> *) a. Monad m => a -> m a
return
{-# INLINE hoistMaybe #-}

-- | Hoist 'Either' m into an 'Either' n.
hoistEitherT :: (forall b. m b -> n b) -> EitherT x m a -> EitherT x n a
hoistEitherT :: forall (m :: * -> *) (n :: * -> *) x a.
(forall b. m b -> n b) -> EitherT x m a -> EitherT x n a
hoistEitherT forall b. m b -> n b
f =
  forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
EitherT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b. m b -> n b
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall x (m :: * -> *) a. EitherT x m a -> m (Either x a)
runEitherT
{-# INLINE hoistEitherT #-}

------------------------------------------------------------------------
-- Error handling

-- | Try an 'IO' action inside an 'EitherT'. If the 'IO' action throws an
-- 'IOException', catch it and wrap it with the provided handler to convert it
-- to the error type of the 'EitherT' transformer. Exceptions other than
-- 'IOException' will escape the EitherT transformer.
--
-- Note: 'IOError' is a type synonym for 'IOException'.
handleIOEitherT :: MonadIO m => (IOException -> x) -> IO a -> EitherT x m a
handleIOEitherT :: forall (m :: * -> *) x a.
MonadIO m =>
(IOException -> x) -> IO a -> EitherT x m a
handleIOEitherT IOException -> x
wrap =
  forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> EitherT x m a -> EitherT y m a
firstEitherT IOException -> x
wrap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
newEitherT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e a. Exception e => IO a -> IO (Either e a)
Exception.try
{-# INLINE handleIOEitherT #-}

-- | Flipped 'handleIOEitherT'.
catchIOEitherT :: MonadIO m => IO a -> (IOException -> x) -> EitherT x m a
catchIOEitherT :: forall (m :: * -> *) a x.
MonadIO m =>
IO a -> (IOException -> x) -> EitherT x m a
catchIOEitherT = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) x a.
MonadIO m =>
(IOException -> x) -> IO a -> EitherT x m a
handleIOEitherT
{-# INLINE catchIOEitherT #-}

-- | Try any monad action and catch the specified exception, wrapping it to
-- convert it to the error type of the 'EitherT' transformer. Exceptions other
-- that the specified exception type will escape the 'EitherT' transformer.
--
-- *Warning*: This function should be used with caution!
-- In particular, it is bad practice to catch 'SomeException' because that
-- includes asynchronous exceptions like stack/heap overflow, thread killed and
-- user interrupt. Trying to handle 'StackOverflow', 'HeapOverflow' and
-- 'ThreadKilled' exceptions could cause your program to crash or behave in
-- unexpected ways.
handleEitherT :: (MonadCatch m, Exception e) => (e -> x) -> m a -> EitherT x m a
handleEitherT :: forall (m :: * -> *) e x a.
(MonadCatch m, Exception e) =>
(e -> x) -> m a -> EitherT x m a
handleEitherT e -> x
wrap =
  forall (m :: * -> *) x y a.
Functor m =>
(x -> y) -> EitherT x m a -> EitherT y m a
firstEitherT e -> x
wrap forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
newEitherT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> m (Either e a)
Catch.try
{-# INLINE handleEitherT #-}

-- | Flipped 'handleEitherT'.
catchEitherT :: (MonadCatch m, Exception e) => m a -> (e -> x) -> EitherT x m a
catchEitherT :: forall (m :: * -> *) e a x.
(MonadCatch m, Exception e) =>
m a -> (e -> x) -> EitherT x m a
catchEitherT = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) e x a.
(MonadCatch m, Exception e) =>
(e -> x) -> m a -> EitherT x m a
handleEitherT
{-# INLINE catchEitherT #-}

-- | Try a monad action and catch any of the exceptions caught by the provided
-- handlers. The handler for each exception type needs to wrap it to convert it
-- to the error type of the 'EitherT' transformer. Exceptions not explicitly
-- handled by the provided handlers will escape the 'EitherT' transformer.
handlesEitherT :: (Foldable f, MonadCatch m) => f (Handler m x) -> m a -> EitherT x m a
handlesEitherT :: forall (f :: * -> *) (m :: * -> *) x a.
(Foldable f, MonadCatch m) =>
f (Handler m x) -> m a -> EitherT x m a
handlesEitherT f (Handler m x)
wrappers m a
action =
  forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
newEitherT (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. b -> Either a b
Right m a
action forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`Catch.catch` forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. a -> Either a b
Left) SomeException -> m x
handler)
  where
    handler :: SomeException -> m x
handler SomeException
e =
      let probe :: Handler m a -> m a -> m a
probe (Handler e -> m a
h) m a
xs =
            forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a
xs e -> m a
h (forall e. Exception e => SomeException -> Maybe e
Exception.fromException SomeException
e)
      in
        forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall {m :: * -> *} {a}. Handler m a -> m a -> m a
probe (forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
Catch.throwM SomeException
e) f (Handler m x)
wrappers

-- | Flipped 'handlesEitherT'.
catchesEitherT  :: (Foldable f, MonadCatch m) => m a -> f (Handler m x) -> EitherT x m a
catchesEitherT :: forall (f :: * -> *) (m :: * -> *) a x.
(Foldable f, MonadCatch m) =>
m a -> f (Handler m x) -> EitherT x m a
catchesEitherT = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) (m :: * -> *) x a.
(Foldable f, MonadCatch m) =>
f (Handler m x) -> m a -> EitherT x m a
handlesEitherT
{-# INLINE catchesEitherT #-}

-- | Handle an error. Equivalent to 'handleError' in mtl package.
handleLeftT :: Monad m => (e -> EitherT e m a) -> EitherT e m a -> EitherT e m a
handleLeftT :: forall (m :: * -> *) e a.
Monad m =>
(e -> EitherT e m a) -> EitherT e m a -> EitherT e m a
handleLeftT e -> EitherT e m a
handler EitherT e m a
thing = do
  Either e a
r <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall a b. (a -> b) -> a -> b
$ forall x (m :: * -> *) a. EitherT x m a -> m (Either x a)
runEitherT EitherT e m a
thing
  case Either e a
r of
    Left e
e ->
      e -> EitherT e m a
handler e
e
    Right a
a ->
      forall (m :: * -> *) a. Monad m => a -> m a
return a
a
{-# INLINE handleLeftT #-}

-- | Flipped 'handleLeftT'.
catchLeftT  :: Monad m => EitherT e m a -> (e -> EitherT e m a) -> EitherT e m a
catchLeftT :: forall (m :: * -> *) e a.
Monad m =>
EitherT e m a -> (e -> EitherT e m a) -> EitherT e m a
catchLeftT = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) e a.
Monad m =>
(e -> EitherT e m a) -> EitherT e m a -> EitherT e m a
handleLeftT
{-# INLINE catchLeftT #-}

-- | Acquire a resource in 'EitherT' and then perform an action with
-- it, cleaning up afterwards regardless of 'left'.
--
-- This function does not clean up in the event of an exception.
-- Prefer 'bracketExceptionT' in any impure setting.
bracketEitherT :: Monad m => EitherT e m a -> (a -> EitherT e m b) -> (a -> EitherT e m c) -> EitherT e m c
bracketEitherT :: forall (m :: * -> *) e a b c.
Monad m =>
EitherT e m a
-> (a -> EitherT e m b) -> (a -> EitherT e m c) -> EitherT e m c
bracketEitherT EitherT e m a
before a -> EitherT e m b
after a -> EitherT e m c
thing = do
    a
a <- EitherT e m a
before
    c
r <- (\e
err -> a -> EitherT e m b
after a
a forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) x a. Monad m => x -> EitherT x m a
left e
err) forall (m :: * -> *) e a.
Monad m =>
(e -> EitherT e m a) -> EitherT e m a -> EitherT e m a
`handleLeftT` a -> EitherT e m c
thing a
a
    -- If handleLeftT already triggered, then `after` already ran *and* we are
    -- in a Left state, so `after` will not run again here.
    b
_ <- a -> EitherT e m b
after a
a
    forall (m :: * -> *) a. Monad m => a -> m a
return c
r
{-# INLINE bracketEitherT #-}

-- | Acquire a resource in EitherT and then perform an action with it,
-- cleaning up afterwards regardless of 'left' or exception.
--
-- Like 'bracketEitherT', but the cleanup is called even when the bracketed
-- function throws an exception. Exceptions in the bracketed function are caught
-- to allow the cleanup to run and then rethrown.
bracketExceptionT ::
     MonadMask m
  => EitherT e m a
  -> (a -> EitherT e m c)
  -> (a -> EitherT e m b)
  -> EitherT e m b
bracketExceptionT :: forall (m :: * -> *) e a c b.
MonadMask m =>
EitherT e m a
-> (a -> EitherT e m c) -> (a -> EitherT e m b) -> EitherT e m b
bracketExceptionT EitherT e m a
acquire a -> EitherT e m c
release a -> EitherT e m b
run =
  forall (m :: * -> *) x a. m (Either x a) -> ExceptT x m a
EitherT forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a b c.
MonadMask m =>
m a -> (a -> m (Either b c)) -> (a -> m b) -> m b
bracketF
    (forall x (m :: * -> *) a. EitherT x m a -> m (Either x a)
runEitherT EitherT e m a
acquire)
    (\Either e a
r -> case Either e a
r of
      Left e
_ ->
        -- Acquire failed, we have nothing to release
        forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ ()
      Right a
r' ->
        -- Acquire succeeded, we need to try and release
        forall x (m :: * -> *) a. EitherT x m a -> m (Either x a)
runEitherT (a -> EitherT e m c
release a
r') forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Either e c
x -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case Either e c
x of
          Left e
err -> forall a b. a -> Either a b
Left (forall a b. a -> Either a b
Left e
err)
          Right c
_ -> forall a b. b -> Either a b
Right ())
    (\Either e a
r -> case Either e a
r of
      Left e
err ->
        -- Acquire failed, we have nothing to run
        forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ e
err
      Right a
r' ->
        -- Acquire succeeded, we can do some work
        forall x (m :: * -> *) a. EitherT x m a -> m (Either x a)
runEitherT (a -> EitherT e m b
run a
r'))
{-# INLINE bracketExceptionT #-}

-- This is for internal use only. The 'bracketF' function catches all exceptions
-- so the cleanup function can be called and then rethrow the exception.
data BracketResult a =
    BracketOk a
  | BracketFailedFinalizerOk SomeException
  | BracketFailedFinalizerError a

-- Bracket where you care about the output of the finalizer. If the finalizer fails
-- with a value level fail, it will return the result of the finalizer.
-- Finalizer:
--  - Left indicates a value level fail.
--  - Right indicates that the finalizer has a value level success, and its results can be ignored.
--
bracketF :: MonadMask m => m a -> (a -> m (Either b c)) -> (a -> m b) -> m b
bracketF :: forall (m :: * -> *) a b c.
MonadMask m =>
m a -> (a -> m (Either b c)) -> (a -> m b) -> m b
bracketF m a
a a -> m (Either b c)
f a -> m b
g =
  forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
mask forall a b. (a -> b) -> a -> b
$ \forall a. m a -> m a
restore -> do
    a
a' <- m a
a
    BracketResult b
x <- forall a. m a -> m a
restore (forall a. a -> BracketResult a
BracketOk forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` a -> m b
g a
a') forall (m :: * -> *) a.
MonadCatch m =>
m a -> (SomeException -> m a) -> m a
`catchAll`
           (\SomeException
ex -> forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a. a -> BracketResult a
BracketFailedFinalizerError (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ forall a. SomeException -> BracketResult a
BracketFailedFinalizerOk SomeException
ex) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` a -> m (Either b c)
f a
a')
    case BracketResult b
x of
      BracketFailedFinalizerOk SomeException
ex ->
        forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM SomeException
ex
      BracketFailedFinalizerError b
b ->
        forall (m :: * -> *) a. Monad m => a -> m a
return b
b
      BracketOk b
b -> do
        Either b c
z <- a -> m (Either b c)
f a
a'
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall a. a -> a
id (forall a b. a -> b -> a
const b
b) Either b c
z
{-# INLINE bracketF #-}

-- | Convert an Either to a Maybe and execute the supplied handler
-- in the Left case.
hushM :: Monad m => Either e a -> (e -> m ()) -> m (Maybe a)
hushM :: forall (m :: * -> *) e a.
Monad m =>
Either e a -> (e -> m ()) -> m (Maybe a)
hushM Either e a
r e -> m ()
f = case Either e a
r of
  Right a
a -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just a
a)
  Left e
e -> e -> m ()
f e
e forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
{-# INLINE hushM #-}

-- | Handle the Left constructor in returned Either.
onLeft :: forall e x m a. Monad m => (e -> ExceptT x m a) -> EitherT x m (Either e a) -> EitherT x m a
onLeft :: forall e x (m :: * -> *) a.
Monad m =>
(e -> ExceptT x m a) -> EitherT x m (Either e a) -> ExceptT x m a
onLeft e -> ExceptT x m a
h EitherT x m (Either e a)
f = EitherT x m (Either e a)
f forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either e -> ExceptT x m a
h forall (m :: * -> *) a. Monad m => a -> m a
return
{-# INLINE onLeft #-}

-- | Handle the Nothing constructor in returned Maybe.
onNothing :: forall x m a. Monad m => EitherT x m a -> EitherT x m (Maybe a) -> EitherT x m a
onNothing :: forall x (m :: * -> *) a.
Monad m =>
EitherT x m a -> EitherT x m (Maybe a) -> EitherT x m a
onNothing EitherT x m a
h EitherT x m (Maybe a)
f = EitherT x m (Maybe a)
f forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall b a. b -> (a -> b) -> Maybe a -> b
maybe EitherT x m a
h forall (m :: * -> *) a. Monad m => a -> m a
return
{-# INLINE onNothing #-}