module Control.Monad.Exception.Asynchronous.Strict (
   Exceptional(..),
   pure,
   broken,
   fromSynchronous,
   fromSynchronousNull,
   fromSynchronousMonoid,
   toSynchronous,
   throw,
   throwMonoid,
   eatNothing,
   zipWith,
   append,
   continue,
   maybeAbort,
   force,
   mapException,
   mapExceptional,
   simultaneousBind,
   simultaneousBindM,
   sequenceF,
   traverse,
   sequenceA,
   mapM,
   sequence,
   swapToSynchronousAsynchronous,
   swapToAsynchronousSynchronous,

   ExceptionalT(..),
   fromSynchronousT,
   fromSynchronousMonoidT,
   forceT,
   mapExceptionT,
   mapExceptionalT,
   throwMonoidT,
   eatNothingT,
   bindT,
   manySynchronousT,
   manyMonoidT,
   processToSynchronousT_,

   appendM,
   continueM,
   ) where

import qualified Control.Monad.Exception.Synchronous as Sync

import Control.Monad (Monad, return, liftM, mplus, join, (>>=), (>>), )
import Control.Applicative (Applicative, liftA, )
import Control.DeepSeq (NFData, rnf, )
import Data.Functor (Functor, fmap, )
{-
import Data.Traversable (Traversable, )
import Data.Foldable (Foldable, )
-}
import Data.Monoid(Monoid, mappend, mempty, )
import Data.Semigroup (Semigroup((<>)), )
import Data.Function (const, (.), ($), )
import Data.Maybe (Maybe(Just, Nothing), maybe, )

import Prelude (Show, )


-- * Plain monad

{- |
Contains a value and a reason why the computation of the value of type @a@ was terminated.
Imagine @a@ as a list type, and an according operation like the 'readFile' operation.
If the exception part is 'Nothing' then the value could be constructed regularly.
If the exception part is 'Just' then the value could not be constructed completely.
However you can read the result of type @a@ lazily,
even if an exception occurs while it is evaluated.
If you evaluate the exception part,
then the result value is certainly computed completely.

However, we cannot provide general 'Monad' functionality
due to the very different ways of combining the results of type @a@.
It is recommended to process the result value in an application specific way,
and after consumption of the result, throw a synchronous exception using 'toSynchronous'.

Maybe in the future we provide a monad instance
which considers subsequent actions as simultaneous processes on a lazy data structure.
-}
data Exceptional e a =
   Exceptional {Exceptional e a -> Maybe e
exception :: Maybe e, Exceptional e a -> a
result :: a}
     deriving Int -> Exceptional e a -> ShowS
[Exceptional e a] -> ShowS
Exceptional e a -> String
(Int -> Exceptional e a -> ShowS)
-> (Exceptional e a -> String)
-> ([Exceptional e a] -> ShowS)
-> Show (Exceptional e a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall e a. (Show e, Show a) => Int -> Exceptional e a -> ShowS
forall e a. (Show e, Show a) => [Exceptional e a] -> ShowS
forall e a. (Show e, Show a) => Exceptional e a -> String
showList :: [Exceptional e a] -> ShowS
$cshowList :: forall e a. (Show e, Show a) => [Exceptional e a] -> ShowS
show :: Exceptional e a -> String
$cshow :: forall e a. (Show e, Show a) => Exceptional e a -> String
showsPrec :: Int -> Exceptional e a -> ShowS
$cshowsPrec :: forall e a. (Show e, Show a) => Int -> Exceptional e a -> ShowS
Show


{- |
Create an exceptional value without exception.
-}
pure :: a -> Exceptional e a
pure :: a -> Exceptional e a
pure = Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e
forall a. Maybe a
Nothing

{- |
Create an exceptional value with exception.
-}
broken :: e -> a -> Exceptional e a
broken :: e -> a -> Exceptional e a
broken e :: e
e = Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (e -> Maybe e
forall a. a -> Maybe a
Just e
e)


fromSynchronous :: a -> Sync.Exceptional e a -> Exceptional e a
fromSynchronous :: a -> Exceptional e a -> Exceptional e a
fromSynchronous deflt :: a
deflt x :: Exceptional e a
x =
   case Exceptional e a
x of
      Sync.Success y :: a
y   -> Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e
forall a. Maybe a
Nothing a
y
      Sync.Exception e :: e
e -> Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (e -> Maybe e
forall a. a -> Maybe a
Just e
e) a
deflt


fromSynchronousNull :: Sync.Exceptional e () -> Exceptional e ()
fromSynchronousNull :: Exceptional e () -> Exceptional e ()
fromSynchronousNull = () -> Exceptional e () -> Exceptional e ()
forall a e. a -> Exceptional e a -> Exceptional e a
fromSynchronous ()

fromSynchronousMonoid :: Monoid a =>
   Sync.Exceptional e a -> Exceptional e a
fromSynchronousMonoid :: Exceptional e a -> Exceptional e a
fromSynchronousMonoid = a -> Exceptional e a -> Exceptional e a
forall a e. a -> Exceptional e a -> Exceptional e a
fromSynchronous a
forall a. Monoid a => a
mempty


toSynchronous :: Exceptional e a -> Sync.Exceptional e a
toSynchronous :: Exceptional e a -> Exceptional e a
toSynchronous (Exceptional me :: Maybe e
me a :: a
a) =
   Exceptional e a
-> (e -> Exceptional e a) -> Maybe e -> Exceptional e a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (a -> Exceptional e a
forall e a. a -> Exceptional e a
Sync.Success a
a) e -> Exceptional e a
forall e a. e -> Exceptional e a
Sync.Exception Maybe e
me


{- |
I think in most cases we want throwMonoid,
thus we can replace 'throw' by 'throwMonoid'.
-}
throw :: e -> Exceptional e ()
throw :: e -> Exceptional e ()
throw e :: e
e = e -> () -> Exceptional e ()
forall e a. e -> a -> Exceptional e a
broken e
e ()

throwMonoid :: Monoid a => e -> Exceptional e a
throwMonoid :: e -> Exceptional e a
throwMonoid e :: e
e = e -> a -> Exceptional e a
forall e a. e -> a -> Exceptional e a
broken e
e a
forall a. Monoid a => a
mempty

{- |
You might use an exception of type @Maybe e@ in 'manyMonoidT'
in order to stop the loop.
After finishing the loop you will want
to turn the @Nothing@ exception into a success.
This is achieved by this function.
-}
eatNothing :: Exceptional (Maybe e) a -> Exceptional e a
eatNothing :: Exceptional (Maybe e) a -> Exceptional e a
eatNothing (Exceptional e :: Maybe (Maybe e)
e a :: a
a) =
   Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (Maybe (Maybe e) -> Maybe e
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join Maybe (Maybe e)
e) a
a


-- ** handling of special result types

{- |
This is an example for application specific handling of result values.
Assume you obtain two lazy lists say from 'readFile'
and you want to zip their contents.
If one of the stream readers emits an exception,
we quit with that exception.
If both streams have throw an exception at the same file position,
the exception of the first stream is propagated.
-}
zipWith ::
   (a -> b -> c) ->
   Exceptional e [a] -> Exceptional e [b] -> Exceptional e [c]
zipWith :: (a -> b -> c)
-> Exceptional e [a] -> Exceptional e [b] -> Exceptional e [c]
zipWith f :: a -> b -> c
f (Exceptional ea :: Maybe e
ea a0 :: [a]
a0) (Exceptional eb :: Maybe e
eb b0 :: [b]
b0) =
   let recourse :: [a] -> [b] -> Exceptional e [c]
recourse (a :: a
a:as :: [a]
as) (b :: b
b:bs :: [b]
bs) =
          ([c] -> [c]) -> Exceptional e [c] -> Exceptional e [c]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> b -> c
f a
a b
b c -> [c] -> [c]
forall a. a -> [a] -> [a]
:) ([a] -> [b] -> Exceptional e [c]
recourseF [a]
as [b]
bs)
       recourse as :: [a]
as _ =
          Maybe e -> [c] -> Exceptional e [c]
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (case [a]
as of [] -> Maybe e -> Maybe e -> Maybe e
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus Maybe e
ea Maybe e
eb; _ -> Maybe e
eb) []
       recourseF :: [a] -> [b] -> Exceptional e [c]
recourseF as :: [a]
as bs :: [b]
bs = [a] -> [b] -> Exceptional e [c]
recourse [a]
as [b]
bs
   in  [a] -> [b] -> Exceptional e [c]
recourseF [a]
a0 [b]
b0


infixr 1 `append`, `continue`, `maybeAbort`

{- |
This is an example for application specific handling of result values.
Assume you obtain two lazy lists say from 'readFile'
and you want to append their contents.
If the first stream ends with an exception,
this exception is kept
and the second stream is not touched.
If the first stream can be read successfully,
the second one is appended until stops.

'append' is less strict than the 'Monoid' method 'mappend' instance.
-}
append ::
   Monoid a =>
   Exceptional e a -> Exceptional e a -> Exceptional e a
append :: Exceptional e a -> Exceptional e a -> Exceptional e a
append (Exceptional ea :: Maybe e
ea a :: a
a) b :: Exceptional e a
b =
   (a -> a) -> Exceptional e a -> Exceptional e a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> a -> a
forall a. Monoid a => a -> a -> a
mappend a
a) (Exceptional e a -> Exceptional e a)
-> Exceptional e a -> Exceptional e a
forall a b. (a -> b) -> a -> b
$ Maybe e -> Exceptional e a -> Exceptional e a
forall a e.
Monoid a =>
Maybe e -> Exceptional e a -> Exceptional e a
continue Maybe e
ea Exceptional e a
b

continue ::
   Monoid a =>
   Maybe e -> Exceptional e a -> Exceptional e a
continue :: Maybe e -> Exceptional e a -> Exceptional e a
continue ea :: Maybe e
ea b :: Exceptional e a
b =
   case Maybe e
ea of
--      Just e  -> throwMonoid e
      Just _  -> Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e
ea a
forall a. Monoid a => a
mempty
      Nothing -> Exceptional e a
b

maybeAbort ::
   Exceptional e a -> Maybe e -> Exceptional e a
maybeAbort :: Exceptional e a -> Maybe e -> Exceptional e a
maybeAbort (Exceptional ea :: Maybe e
ea a :: a
a) eb :: Maybe e
eb =
   Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (Maybe e -> Maybe e -> Maybe e
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus Maybe e
ea Maybe e
eb) a
a


instance (NFData e, NFData a) => NFData (Exceptional e a) where
   rnf :: Exceptional e a -> ()
rnf (Exceptional e :: Maybe e
e a :: a
a) = (Maybe e, a) -> ()
forall a. NFData a => a -> ()
rnf (Maybe e
e, a
a)

instance Monoid a => Semigroup (Exceptional e a) where
   Exceptional ea :: Maybe e
ea a :: a
a <> :: Exceptional e a -> Exceptional e a -> Exceptional e a
<> Exceptional eb :: Maybe e
eb b :: a
b =
      Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (Maybe e -> Maybe e -> Maybe e
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus Maybe e
ea Maybe e
eb) (a -> a -> a
forall a. Monoid a => a -> a -> a
mappend a
a (a -> (e -> a) -> Maybe e -> a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe a
b (a -> e -> a
forall a b. a -> b -> a
const a
forall a. Monoid a => a
mempty) Maybe e
ea))

{- |
'mappend' must be strict in order to fulfill the Monoid laws
@mappend mempty a = a@ and @mappend a mempty = a@ for @a=undefined@.
-}
instance Monoid a => Monoid (Exceptional e a) where
   mempty :: Exceptional e a
mempty = a -> Exceptional e a
forall a e. a -> Exceptional e a
pure a
forall a. Monoid a => a
mempty
--   mappend = append
   mappend :: Exceptional e a -> Exceptional e a -> Exceptional e a
mappend = Exceptional e a -> Exceptional e a -> Exceptional e a
forall a. Semigroup a => a -> a -> a
(<>)


{- | construct Exceptional constructor lazily -}
{-# INLINE force #-}
force :: Exceptional e a -> Exceptional e a
force :: Exceptional e a -> Exceptional e a
force ~(Exceptional e :: Maybe e
e a :: a
a) = Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e
e a
a

mapException :: (e0 -> e1) -> Exceptional e0 a -> Exceptional e1 a
mapException :: (e0 -> e1) -> Exceptional e0 a -> Exceptional e1 a
mapException f :: e0 -> e1
f (Exceptional e :: Maybe e0
e a :: a
a) = Maybe e1 -> a -> Exceptional e1 a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional ((e0 -> e1) -> Maybe e0 -> Maybe e1
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap e0 -> e1
f Maybe e0
e) a
a

mapExceptional :: (e0 -> e1) -> (a -> b) -> Exceptional e0 a -> Exceptional e1 b
mapExceptional :: (e0 -> e1) -> (a -> b) -> Exceptional e0 a -> Exceptional e1 b
mapExceptional f :: e0 -> e1
f g :: a -> b
g (Exceptional e :: Maybe e0
e a :: a
a) = Maybe e1 -> b -> Exceptional e1 b
forall e a. Maybe e -> a -> Exceptional e a
Exceptional ((e0 -> e1) -> Maybe e0 -> Maybe e1
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap e0 -> e1
f Maybe e0
e) (a -> b
g a
a)

{-
This definition actually fulfills the Functor laws:

> fmap (f.g) = fmap f . fmap g
> fmap id = id
-}
instance Functor (Exceptional e) where
   fmap :: (a -> b) -> Exceptional e a -> Exceptional e b
fmap f :: a -> b
f (Exceptional e :: Maybe e
e a :: a
a) = Maybe e -> b -> Exceptional e b
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e
e (a -> b
f a
a)


infixr 1 `simultaneousBind`, `simultaneousBindM`

{- |
I consider both actions to process the data simultaneously through lazy evaluation.
If the second one fails too, it must have encountered an exception
in the data that was successfully emitted by the first action,
and thus the exception of the second action is probably earlier.

We cannot check in general whether the two exception occur at the same time,
e.g. the second one might occur since the first occured and left an invalid structure.
In this case we should emit the first exception, not the second one.
Because of this I expect that this function is not particularly useful.
Otherwise it could be used as bind operation for a monad instance.
-}
{-# DEPRECATED simultaneousBind, simultaneousBindM "Check whether this function is really what you need. It generates an unreasonable exception when the second exception is caused by the first one." #-}
simultaneousBind :: Exceptional e a -> (a -> Exceptional e b) -> Exceptional e b
simultaneousBind :: Exceptional e a -> (a -> Exceptional e b) -> Exceptional e b
simultaneousBind (Exceptional mea :: Maybe e
mea a :: a
a) actB :: a -> Exceptional e b
actB =
   let Exceptional meb :: Maybe e
meb b :: b
b = a -> Exceptional e b
actB a
a
   in  Maybe e -> b -> Exceptional e b
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (Maybe e -> Maybe e -> Maybe e
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus Maybe e
meb Maybe e
mea) b
b

simultaneousBindM :: (Monad m) => m (Exceptional e a) -> (a -> m (Exceptional e b)) -> m (Exceptional e b)
simultaneousBindM :: m (Exceptional e a)
-> (a -> m (Exceptional e b)) -> m (Exceptional e b)
simultaneousBindM actA :: m (Exceptional e a)
actA actB :: a -> m (Exceptional e b)
actB =
   do Exceptional mea :: Maybe e
mea a :: a
a <- m (Exceptional e a)
actA
      Exceptional meb :: Maybe e
meb b :: b
b <- a -> m (Exceptional e b)
actB a
a
      Exceptional e b -> m (Exceptional e b)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe e -> b -> Exceptional e b
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (Maybe e -> Maybe e -> Maybe e
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus Maybe e
meb Maybe e
mea) b
b)


-- | Is there a better name?
{-# INLINE sequenceF #-}
sequenceF :: Functor f => Exceptional e (f a) -> f (Exceptional e a)
sequenceF :: Exceptional e (f a) -> f (Exceptional e a)
sequenceF (Exceptional e :: Maybe e
e a :: f a
a) =
   (a -> Exceptional e a) -> f a -> f (Exceptional e a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e
e) f a
a

-- instance Foldable (Exceptional e) where

-- instance Traversable (Exceptional e) where

{- |
@Foldable@ instance would allow to strip off the exception too easily.

I like the methods of @Traversable@, but @Traversable@ instance requires @Foldable@ instance.
-}

{-# INLINE traverse #-}
traverse :: Applicative f => (a -> f b) -> Exceptional e a -> f (Exceptional e b)
traverse :: (a -> f b) -> Exceptional e a -> f (Exceptional e b)
traverse f :: a -> f b
f = Exceptional e (f b) -> f (Exceptional e b)
forall (f :: * -> *) e a.
Applicative f =>
Exceptional e (f a) -> f (Exceptional e a)
sequenceA (Exceptional e (f b) -> f (Exceptional e b))
-> (Exceptional e a -> Exceptional e (f b))
-> Exceptional e a
-> f (Exceptional e b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> f b) -> Exceptional e a -> Exceptional e (f b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> f b
f

{-# INLINE sequenceA #-}
sequenceA :: Applicative f => Exceptional e (f a) -> f (Exceptional e a)
sequenceA :: Exceptional e (f a) -> f (Exceptional e a)
sequenceA (Exceptional e :: Maybe e
e a :: f a
a) =
   (a -> Exceptional e a) -> f a -> f (Exceptional e a)
forall (f :: * -> *) a b. Applicative f => (a -> b) -> f a -> f b
liftA (Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e
e) f a
a

{-# INLINE mapM #-}
mapM :: Monad m => (a -> m b) -> Exceptional e a -> m (Exceptional e b)
mapM :: (a -> m b) -> Exceptional e a -> m (Exceptional e b)
mapM f :: a -> m b
f = Exceptional e (m b) -> m (Exceptional e b)
forall (m :: * -> *) e a.
Monad m =>
Exceptional e (m a) -> m (Exceptional e a)
sequence (Exceptional e (m b) -> m (Exceptional e b))
-> (Exceptional e a -> Exceptional e (m b))
-> Exceptional e a
-> m (Exceptional e b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> m b) -> Exceptional e a -> Exceptional e (m b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> m b
f

{-# INLINE sequence #-}
sequence :: Monad m => Exceptional e (m a) -> m (Exceptional e a)
sequence :: Exceptional e (m a) -> m (Exceptional e a)
sequence (Exceptional e :: Maybe e
e a :: m a
a) =
   (a -> Exceptional e a) -> m a -> m (Exceptional e a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Maybe e -> a -> Exceptional e a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e
e) m a
a



{-
instance Applicative (Exceptional e) where
   pure = pure
   f <*> x =
      case f of
         Exceptional e0 g ->
            case x of
               Exceptional e1 y -> Exceptional (mplus e0 e1) (g y)

instance Monad (Exceptional e) where
   return = pure
   fail _msg =
      Exceptional
         [Just (error "Asynchronous.fail exception")]
         (error "Asynchronous.fail result")
   x >>= f =
      case x of
         Exceptional e0 y ->
            case f y of
               Exceptional e1 z -> Exceptional (e0 ++ e1) z
-}

{- |
Consider a file format consisting of a header and a data body.
The header can only be used if is read completely.
Its parsing might stop with an synchronous exception.
The data body can also be used if it is truncated by an exceptional event.
This is expressed by an asynchronous exception.
A loader for this file format can thus fail
by a synchronous and an asynchronous exception.
Surprisingly, both orders of nesting these two kinds of exceptional actions
are equally expressive.
This function converts to the form where the synchronous exception is the outer one.

This is a specialisation of 'sequence' and friends.
-}
swapToSynchronousAsynchronous :: Exceptional e0 (Sync.Exceptional e1 a) -> Sync.Exceptional e1 (Exceptional e0 a)
swapToSynchronousAsynchronous :: Exceptional e0 (Exceptional e1 a)
-> Exceptional e1 (Exceptional e0 a)
swapToSynchronousAsynchronous (Exceptional e0 :: Maybe e0
e0 x :: Exceptional e1 a
x) =
   (a -> Exceptional e0 a)
-> Exceptional e1 a -> Exceptional e1 (Exceptional e0 a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Maybe e0 -> a -> Exceptional e0 a
forall e a. Maybe e -> a -> Exceptional e a
Exceptional Maybe e0
e0) Exceptional e1 a
x

swapToAsynchronousSynchronous :: Sync.Exceptional e1 (Exceptional e0 a) -> Exceptional e0 (Sync.Exceptional e1 a)
swapToAsynchronousSynchronous :: Exceptional e1 (Exceptional e0 a)
-> Exceptional e0 (Exceptional e1 a)
swapToAsynchronousSynchronous x :: Exceptional e1 (Exceptional e0 a)
x =
--   Traversable.sequenceA x
   case Exceptional e1 (Exceptional e0 a)
x of
      Sync.Exception e1 :: e1
e1 -> Exceptional e1 a -> Exceptional e0 (Exceptional e1 a)
forall a e. a -> Exceptional e a
pure (Exceptional e1 a -> Exceptional e0 (Exceptional e1 a))
-> Exceptional e1 a -> Exceptional e0 (Exceptional e1 a)
forall a b. (a -> b) -> a -> b
$ e1 -> Exceptional e1 a
forall e a. e -> Exceptional e a
Sync.Exception e1
e1
      Sync.Success s :: Exceptional e0 a
s -> (a -> Exceptional e1 a)
-> Exceptional e0 a -> Exceptional e0 (Exceptional e1 a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Exceptional e1 a
forall e a. a -> Exceptional e a
Sync.Success Exceptional e0 a
s


-- * Monad/Monoid transformer

{- |
In contrast to synchronous exceptions,
the asynchronous monad transformer is not quite a monad.
You must use the 'Monoid' interface or 'bindT' instead.
-}
newtype ExceptionalT e m a =
   ExceptionalT {ExceptionalT e m a -> m (Exceptional e a)
runExceptionalT :: m (Exceptional e a)}


fromSynchronousT :: Functor m =>
   a -> Sync.ExceptionalT e m a -> ExceptionalT e m a
fromSynchronousT :: a -> ExceptionalT e m a -> ExceptionalT e m a
fromSynchronousT deflt :: a
deflt =
   m (Exceptional e a) -> ExceptionalT e m a
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT (m (Exceptional e a) -> ExceptionalT e m a)
-> (ExceptionalT e m a -> m (Exceptional e a))
-> ExceptionalT e m a
-> ExceptionalT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (Exceptional e a -> Exceptional e a)
-> m (Exceptional e a) -> m (Exceptional e a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> Exceptional e a -> Exceptional e a
forall a e. a -> Exceptional e a -> Exceptional e a
fromSynchronous a
deflt) (m (Exceptional e a) -> m (Exceptional e a))
-> (ExceptionalT e m a -> m (Exceptional e a))
-> ExceptionalT e m a
-> m (Exceptional e a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   ExceptionalT e m a -> m (Exceptional e a)
forall e (m :: * -> *) a. ExceptionalT e m a -> m (Exceptional e a)
Sync.runExceptionalT

fromSynchronousMonoidT :: (Functor m, Monoid a) =>
   Sync.ExceptionalT e m a -> ExceptionalT e m a
fromSynchronousMonoidT :: ExceptionalT e m a -> ExceptionalT e m a
fromSynchronousMonoidT =
   a -> ExceptionalT e m a -> ExceptionalT e m a
forall (m :: * -> *) a e.
Functor m =>
a -> ExceptionalT e m a -> ExceptionalT e m a
fromSynchronousT a
forall a. Monoid a => a
mempty


instance Functor m => Functor (ExceptionalT e m) where
   fmap :: (a -> b) -> ExceptionalT e m a -> ExceptionalT e m b
fmap f :: a -> b
f (ExceptionalT x :: m (Exceptional e a)
x) =
      m (Exceptional e b) -> ExceptionalT e m b
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT ((Exceptional e a -> Exceptional e b)
-> m (Exceptional e a) -> m (Exceptional e b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> Exceptional e a -> Exceptional e b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f) m (Exceptional e a)
x)

instance (Monad m, Monoid a) => Semigroup (ExceptionalT e m a) where
   x :: ExceptionalT e m a
x <> :: ExceptionalT e m a -> ExceptionalT e m a -> ExceptionalT e m a
<> y :: ExceptionalT e m a
y =
      m (Exceptional e a) -> ExceptionalT e m a
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT (m (Exceptional e a) -> ExceptionalT e m a)
-> m (Exceptional e a) -> ExceptionalT e m a
forall a b. (a -> b) -> a -> b
$
      m (Exceptional e a) -> m (Exceptional e a) -> m (Exceptional e a)
forall (m :: * -> *) a e.
(Monad m, Monoid a) =>
m (Exceptional e a) -> m (Exceptional e a) -> m (Exceptional e a)
appendM (ExceptionalT e m a -> m (Exceptional e a)
forall e (m :: * -> *) a. ExceptionalT e m a -> m (Exceptional e a)
runExceptionalT ExceptionalT e m a
x) (ExceptionalT e m a -> m (Exceptional e a)
forall e (m :: * -> *) a. ExceptionalT e m a -> m (Exceptional e a)
runExceptionalT ExceptionalT e m a
y)

instance (Monad m, Monoid a) => Monoid (ExceptionalT e m a) where
   mempty :: ExceptionalT e m a
mempty = m (Exceptional e a) -> ExceptionalT e m a
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT (m (Exceptional e a) -> ExceptionalT e m a)
-> m (Exceptional e a) -> ExceptionalT e m a
forall a b. (a -> b) -> a -> b
$ Exceptional e a -> m (Exceptional e a)
forall (m :: * -> *) a. Monad m => a -> m a
return Exceptional e a
forall a. Monoid a => a
mempty
   mappend :: ExceptionalT e m a -> ExceptionalT e m a -> ExceptionalT e m a
mappend = ExceptionalT e m a -> ExceptionalT e m a -> ExceptionalT e m a
forall a. Semigroup a => a -> a -> a
(<>)

{-
instance Applicative m => Applicative (ExceptionalT e m) where
   pure = ExceptionalT . pure . pure
   ExceptionalT f <*> ExceptionalT x =
      ExceptionalT (fmap (<*>) f <*> x)

instance Monad m => Monad (ExceptionalT e m) where
   return = ExceptionalT . return . return
   x0 >>= f =
      ExceptionalT $
      do Exceptional ex x <- runExceptionalT x0
         Exceptional ey y <- runExceptionalT (f x)
         return $ Exceptional (ex ++ ey) y
-}


{- |
see 'force'
-}
forceT :: Monad m => ExceptionalT e m a -> ExceptionalT e m a
forceT :: ExceptionalT e m a -> ExceptionalT e m a
forceT =
   m (Exceptional e a) -> ExceptionalT e m a
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT (m (Exceptional e a) -> ExceptionalT e m a)
-> (ExceptionalT e m a -> m (Exceptional e a))
-> ExceptionalT e m a
-> ExceptionalT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exceptional e a -> Exceptional e a)
-> m (Exceptional e a) -> m (Exceptional e a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Exceptional e a -> Exceptional e a
forall e a. Exceptional e a -> Exceptional e a
force (m (Exceptional e a) -> m (Exceptional e a))
-> (ExceptionalT e m a -> m (Exceptional e a))
-> ExceptionalT e m a
-> m (Exceptional e a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExceptionalT e m a -> m (Exceptional e a)
forall e (m :: * -> *) a. ExceptionalT e m a -> m (Exceptional e a)
runExceptionalT

mapExceptionT :: (Monad m) =>
   (e0 -> e1) ->
   ExceptionalT e0 m a ->
   ExceptionalT e1 m a
mapExceptionT :: (e0 -> e1) -> ExceptionalT e0 m a -> ExceptionalT e1 m a
mapExceptionT f :: e0 -> e1
f =
   m (Exceptional e1 a) -> ExceptionalT e1 m a
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT (m (Exceptional e1 a) -> ExceptionalT e1 m a)
-> (ExceptionalT e0 m a -> m (Exceptional e1 a))
-> ExceptionalT e0 m a
-> ExceptionalT e1 m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exceptional e0 a -> Exceptional e1 a)
-> m (Exceptional e0 a) -> m (Exceptional e1 a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((e0 -> e1) -> Exceptional e0 a -> Exceptional e1 a
forall e0 e1 a. (e0 -> e1) -> Exceptional e0 a -> Exceptional e1 a
mapException e0 -> e1
f) (m (Exceptional e0 a) -> m (Exceptional e1 a))
-> (ExceptionalT e0 m a -> m (Exceptional e0 a))
-> ExceptionalT e0 m a
-> m (Exceptional e1 a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExceptionalT e0 m a -> m (Exceptional e0 a)
forall e (m :: * -> *) a. ExceptionalT e m a -> m (Exceptional e a)
runExceptionalT

mapExceptionalT ::
   (m (Exceptional e0 a) -> n (Exceptional e1 b)) ->
   ExceptionalT e0 m a -> ExceptionalT e1 n b
mapExceptionalT :: (m (Exceptional e0 a) -> n (Exceptional e1 b))
-> ExceptionalT e0 m a -> ExceptionalT e1 n b
mapExceptionalT f :: m (Exceptional e0 a) -> n (Exceptional e1 b)
f =
   n (Exceptional e1 b) -> ExceptionalT e1 n b
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT (n (Exceptional e1 b) -> ExceptionalT e1 n b)
-> (ExceptionalT e0 m a -> n (Exceptional e1 b))
-> ExceptionalT e0 m a
-> ExceptionalT e1 n b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m (Exceptional e0 a) -> n (Exceptional e1 b)
f (m (Exceptional e0 a) -> n (Exceptional e1 b))
-> (ExceptionalT e0 m a -> m (Exceptional e0 a))
-> ExceptionalT e0 m a
-> n (Exceptional e1 b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExceptionalT e0 m a -> m (Exceptional e0 a)
forall e (m :: * -> *) a. ExceptionalT e m a -> m (Exceptional e a)
runExceptionalT


throwMonoidT :: (Monad m, Monoid a) =>
   e -> ExceptionalT e m a
throwMonoidT :: e -> ExceptionalT e m a
throwMonoidT = m (Exceptional e a) -> ExceptionalT e m a
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT (m (Exceptional e a) -> ExceptionalT e m a)
-> (e -> m (Exceptional e a)) -> e -> ExceptionalT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Exceptional e a -> m (Exceptional e a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Exceptional e a -> m (Exceptional e a))
-> (e -> Exceptional e a) -> e -> m (Exceptional e a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Exceptional e a
forall a e. Monoid a => e -> Exceptional e a
throwMonoid


eatNothingT :: Monad m =>
   ExceptionalT (Maybe e) m a -> ExceptionalT e m a
eatNothingT :: ExceptionalT (Maybe e) m a -> ExceptionalT e m a
eatNothingT =
   (m (Exceptional (Maybe e) a) -> m (Exceptional e a))
-> ExceptionalT (Maybe e) m a -> ExceptionalT e m a
forall (m :: * -> *) e0 a (n :: * -> *) e1 b.
(m (Exceptional e0 a) -> n (Exceptional e1 b))
-> ExceptionalT e0 m a -> ExceptionalT e1 n b
mapExceptionalT ((Exceptional (Maybe e) a -> Exceptional e a)
-> m (Exceptional (Maybe e) a) -> m (Exceptional e a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Exceptional (Maybe e) a -> Exceptional e a
forall e a. Exceptional (Maybe e) a -> Exceptional e a
eatNothing)


infixl 1 `bindT`

{- |
The monadic bind operation.
It cannot be made an instance of the Monad class method @(>>=)@
since it requires a default return value
in case the first action fails.
We get this default value by the 'Monoid' method 'mempty'.
-}
bindT :: (Monad m, Monoid b) =>
   ExceptionalT e m a ->
   (a -> ExceptionalT e m b) ->
   ExceptionalT e m b
bindT :: ExceptionalT e m a
-> (a -> ExceptionalT e m b) -> ExceptionalT e m b
bindT x :: ExceptionalT e m a
x y :: a -> ExceptionalT e m b
y =
   m (Exceptional e b) -> ExceptionalT e m b
forall e (m :: * -> *) a. m (Exceptional e a) -> ExceptionalT e m a
ExceptionalT (m (Exceptional e b) -> ExceptionalT e m b)
-> m (Exceptional e b) -> ExceptionalT e m b
forall a b. (a -> b) -> a -> b
$
   ExceptionalT e m a -> m (Exceptional e a)
forall e (m :: * -> *) a. ExceptionalT e m a -> m (Exceptional e a)
runExceptionalT ExceptionalT e m a
x m (Exceptional e a)
-> (Exceptional e a -> m (Exceptional e b)) -> m (Exceptional e b)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \r :: Exceptional e a
r ->
   ExceptionalT e m b -> m (Exceptional e b)
forall e (m :: * -> *) a. ExceptionalT e m a -> m (Exceptional e a)
runExceptionalT (ExceptionalT e m b -> m (Exceptional e b))
-> ExceptionalT e m b -> m (Exceptional e b)
forall a b. (a -> b) -> a -> b
$ ExceptionalT e m b
-> (e -> ExceptionalT e m b) -> Maybe e -> ExceptionalT e m b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (a -> ExceptionalT e m b
y (a -> ExceptionalT e m b) -> a -> ExceptionalT e m b
forall a b. (a -> b) -> a -> b
$ Exceptional e a -> a
forall e a. Exceptional e a -> a
result Exceptional e a
r) e -> ExceptionalT e m b
forall (m :: * -> *) a e.
(Monad m, Monoid a) =>
e -> ExceptionalT e m a
throwMonoidT (Exceptional e a -> Maybe e
forall e a. Exceptional e a -> Maybe e
exception Exceptional e a
r)


infixr 1 {- `bindM`, -} `appendM`, `continueM`

{-
bindM :: (Monad m, Monoid b) => SynchronousExceptional m a -> (a -> AsynchronousExceptional m b) -> AsynchronousExceptional m b
bindM x y =
   Sync.tryT x >>= \result ->
      liftM Async.force
      (case result of
         Sync.Exception e -> return $ Async.throwMonoid e
         Sync.Success s -> y s)
-}

appendM :: (Monad m, Monoid a) =>
   m (Exceptional e a) -> m (Exceptional e a) -> m (Exceptional e a)
appendM :: m (Exceptional e a) -> m (Exceptional e a) -> m (Exceptional e a)
appendM x :: m (Exceptional e a)
x y :: m (Exceptional e a)
y =
   do Exceptional e a
r <- m (Exceptional e a)
x
      (Exceptional e a -> Exceptional e a)
-> m (Exceptional e a) -> m (Exceptional e a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((a -> a) -> Exceptional e a -> Exceptional e a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> a -> a
forall a. Monoid a => a -> a -> a
mappend (Exceptional e a -> a
forall e a. Exceptional e a -> a
result Exceptional e a
r))) (m (Exceptional e a) -> m (Exceptional e a))
-> m (Exceptional e a) -> m (Exceptional e a)
forall a b. (a -> b) -> a -> b
$
         Maybe e -> m (Exceptional e a) -> m (Exceptional e a)
forall (m :: * -> *) a e.
(Monad m, Monoid a) =>
Maybe e -> m (Exceptional e a) -> m (Exceptional e a)
continueMPlain (Exceptional e a -> Maybe e
forall e a. Exceptional e a -> Maybe e
exception Exceptional e a
r) m (Exceptional e a)
y

continueM :: (Monad m, Monoid a) =>
   m (Maybe e) -> m (Exceptional e a) -> m (Exceptional e a)
continueM :: m (Maybe e) -> m (Exceptional e a) -> m (Exceptional e a)
continueM mx :: m (Maybe e)
mx y :: m (Exceptional e a)
y =
   m (Maybe e)
mx m (Maybe e)
-> (Maybe e -> m (Exceptional e a)) -> m (Exceptional e a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \x :: Maybe e
x -> Maybe e -> m (Exceptional e a) -> m (Exceptional e a)
forall (m :: * -> *) a e.
(Monad m, Monoid a) =>
Maybe e -> m (Exceptional e a) -> m (Exceptional e a)
continueMPlain Maybe e
x m (Exceptional e a)
y

continueMPlain :: (Monad m, Monoid a) =>
   Maybe e -> m (Exceptional e a) -> m (Exceptional e a)
continueMPlain :: Maybe e -> m (Exceptional e a) -> m (Exceptional e a)
continueMPlain x :: Maybe e
x y :: m (Exceptional e a)
y =
   m (Exceptional e a)
-> (e -> m (Exceptional e a)) -> Maybe e -> m (Exceptional e a)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m (Exceptional e a)
y (Exceptional e a -> m (Exceptional e a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Exceptional e a -> m (Exceptional e a))
-> (e -> Exceptional e a) -> e -> m (Exceptional e a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> Exceptional e a
forall a e. Monoid a => e -> Exceptional e a
throwMonoid) Maybe e
x


{- |
Repeat an action with synchronous exceptions until an exception occurs.
Combine all atomic results using the @bind@ function.
It may be @cons = (:)@ and @empty = []@ for @b@ being a list type.
The @defer@ function may be @id@
or @unsafeInterleaveIO@ for lazy read operations.
The exception is returned as asynchronous exception.
-}
manySynchronousT :: (Monad m) =>
   (m (Exceptional e b) -> m (Exceptional e b))
                           {- ^ @defer@ function -} ->
   (a -> b -> b)           {- ^ @cons@ function -} ->
   b                       {- ^ @empty@ -} ->
   Sync.ExceptionalT e m a {- ^ atomic action to repeat -} ->
   m (Exceptional e b)
manySynchronousT :: (m (Exceptional e b) -> m (Exceptional e b))
-> (a -> b -> b) -> b -> ExceptionalT e m a -> m (Exceptional e b)
manySynchronousT defer :: m (Exceptional e b) -> m (Exceptional e b)
defer cons :: a -> b -> b
cons empty :: b
empty action :: ExceptionalT e m a
action =
   let recourse :: m (Exceptional e b)
recourse =
          m (Exceptional e b) -> m (Exceptional e b)
defer (m (Exceptional e b) -> m (Exceptional e b))
-> m (Exceptional e b) -> m (Exceptional e b)
forall a b. (a -> b) -> a -> b
$
          do Exceptional e a
r <- ExceptionalT e m a -> m (Exceptional e a)
forall (m :: * -> *) e a.
Monad m =>
ExceptionalT e m a -> m (Exceptional e a)
Sync.tryT ExceptionalT e m a
action
             case Exceptional e a
r of
                Sync.Exception e :: e
e -> Exceptional e b -> m (Exceptional e b)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe e -> b -> Exceptional e b
forall e a. Maybe e -> a -> Exceptional e a
Exceptional (e -> Maybe e
forall a. a -> Maybe a
Just e
e) b
empty)
                Sync.Success x :: a
x   -> (Exceptional e b -> Exceptional e b)
-> m (Exceptional e b) -> m (Exceptional e b)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((b -> b) -> Exceptional e b -> Exceptional e b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> b -> b
cons a
x)) m (Exceptional e b)
recourse
   in  m (Exceptional e b)
recourse

{-# DEPRECATED manySynchronousT "use manyMonoidT with appropriate Monad like LazyIO and result Monoid like Endo instead" #-}

{- |
We advise to use the Endo Monoid
when you want to read a series of characters into a list.
This means you use the difference lists technique
in order to build the list, which is efficient.

> import Data.Monoid (Endo, appEndo, )
> import Control.Exception (try, )
> import qualified Control.Monad.Exception.Synchronous as Sync

> fmap (flip appEndo []) $ manyMonoidT (fromSynchronousMonoidT $ fmap (Endo . (:)) $ Sync.fromEitherT $ try getChar)

If you want Lazy IO you must additionally convert @getChar@ to LazyIO monad.
-}
manyMonoidT :: (Monad m, Monoid a) =>
   ExceptionalT e m a {- ^ atomic action to repeat -} ->
   ExceptionalT e m a
manyMonoidT :: ExceptionalT e m a -> ExceptionalT e m a
manyMonoidT act :: ExceptionalT e m a
act =
   let -- like fmap, but doesn't require Functor instance of @m@
       customFmap :: (a -> b) -> ExceptionalT e1 n a -> ExceptionalT e1 n b
customFmap f :: a -> b
f = (n (Exceptional e1 a) -> n (Exceptional e1 b))
-> ExceptionalT e1 n a -> ExceptionalT e1 n b
forall (m :: * -> *) e0 a (n :: * -> *) e1 b.
(m (Exceptional e0 a) -> n (Exceptional e1 b))
-> ExceptionalT e0 m a -> ExceptionalT e1 n b
mapExceptionalT ((Exceptional e1 a -> Exceptional e1 b)
-> n (Exceptional e1 a) -> n (Exceptional e1 b)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((a -> b) -> Exceptional e1 a -> Exceptional e1 b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f))
       go :: ExceptionalT e m a
go = ExceptionalT e m a
act ExceptionalT e m a
-> (a -> ExceptionalT e m a) -> ExceptionalT e m a
forall (m :: * -> *) b e a.
(Monad m, Monoid b) =>
ExceptionalT e m a
-> (a -> ExceptionalT e m b) -> ExceptionalT e m b
`bindT` \r :: a
r -> (a -> a) -> ExceptionalT e m a -> ExceptionalT e m a
forall (n :: * -> *) a b e1.
Monad n =>
(a -> b) -> ExceptionalT e1 n a -> ExceptionalT e1 n b
customFmap (a -> a -> a
forall a. Monoid a => a -> a -> a
mappend a
r) ExceptionalT e m a
go
   in  ExceptionalT e m a
go

{- |
Scan @x@ using the @decons@ function
and run an action with synchronous exceptions for each element fetched from @x@.
Each invocation of an element action may stop this function
due to an exception.
If all element actions can be performed successfully
and if there is an asynchronous exception
then at the end this exception is raised as synchronous exception.
@decons@ function might be @Data.List.HT.viewL@.
-}
processToSynchronousT_ :: (Monad m) =>
   (b -> Maybe (a,b))  {- ^ decons function -} ->
   (a -> Sync.ExceptionalT e m ())
                       {- ^ action that is run for each element fetched from @x@ -} ->
   Exceptional e b     {- ^ value @x@ of type @b@ with asynchronous exception -} ->
   Sync.ExceptionalT e m ()
processToSynchronousT_ :: (b -> Maybe (a, b))
-> (a -> ExceptionalT e m ())
-> Exceptional e b
-> ExceptionalT e m ()
processToSynchronousT_ decons :: b -> Maybe (a, b)
decons action :: a -> ExceptionalT e m ()
action (Exceptional me :: Maybe e
me x :: b
x) =
   let recourse :: b -> ExceptionalT e m ()
recourse b0 :: b
b0 =
          ExceptionalT e m ()
-> ((a, b) -> ExceptionalT e m ())
-> Maybe (a, b)
-> ExceptionalT e m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
             (ExceptionalT e m ()
-> (e -> ExceptionalT e m ()) -> Maybe e -> ExceptionalT e m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> ExceptionalT e m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) e -> ExceptionalT e m ()
forall (m :: * -> *) e a. Monad m => e -> ExceptionalT e m a
Sync.throwT Maybe e
me)
             (\(a :: a
a,b1 :: b
b1) -> a -> ExceptionalT e m ()
action a
a ExceptionalT e m () -> ExceptionalT e m () -> ExceptionalT e m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> ExceptionalT e m ()
recourse b
b1)
             (b -> Maybe (a, b)
decons b
b0)
   in  b -> ExceptionalT e m ()
recourse b
x