#ifdef KIND_POLYMORPHIC_TYPEABLE
#endif
#ifdef GHC_GENERICS
#endif
module Control.Monad.TaggedException.Internal.Throws
(
Throws(..)
, liftBindLike
, liftCCLike
, liftEmbedLike
, liftHoistLike
, liftMask
)
where
import Control.Applicative
( Alternative((<|>), empty, many, some)
, Applicative((<*), (<*>), (*>), pure)
)
import Control.Monad
( Monad((>>), (>>=), fail, return)
, MonadPlus(mplus, mzero)
)
import Data.Functor (Functor(fmap))
import Data.Function ((.))
import Data.Monoid (Monoid)
#ifdef KIND_POLYMORPHIC_TYPEABLE
import Data.Typeable (Typeable)
#endif
#ifdef GHC_GENERICS
import GHC.Generics (Generic)
#endif
import Control.Monad.Cont.Class (MonadCont(callCC))
import Control.Monad.Error.Class (MonadError(catchError, throwError))
import Control.Monad.IO.Class (MonadIO(liftIO))
import Control.Monad.Reader.Class (MonadReader(ask, local, reader))
import Control.Monad.RWS.Class (MonadRWS)
import Control.Monad.State.Class (MonadState(get, put, state))
import Control.Monad.Trans.Class (MonadTrans(lift))
import Control.Monad.Writer.Class (MonadWriter(listen, pass, tell, writer))
import Control.Monad.Catch
( MonadCatch(catch)
, MonadMask(mask, uninterruptibleMask)
, MonadThrow(throwM)
)
import Control.Monad.Morph (MFunctor(hoist), MMonad(embed))
newtype Throws e m a = Throws
{ hideException :: m a
}
#ifdef GHC_GENERICS
deriving
( Generic
#ifdef KIND_POLYMORPHIC_TYPEABLE
, Typeable
#endif
)
#endif
liftBindLike
:: (m a -> (b -> m c) -> m d)
-> Throws e m a
-> (b -> Throws e m c)
-> Throws e m d
liftBindLike f x g = Throws (f (hideException x) (hideException . g))
liftCCLike
:: (((a -> m b) -> m' c) -> m'' d)
-> ((a -> Throws e m b) -> Throws e m' c) -> Throws e m'' d
liftCCLike f g = Throws (f (\h -> hideException (g (Throws . h))))
liftMask
:: (((forall a. m a -> m a) -> m b) -> m b)
-> ((forall a. Throws e m a -> Throws e m a) -> Throws e m b)
-> Throws e m b
liftMask msk f = Throws (msk (\restore -> hideException (f (liftT restore))))
where
liftT :: (m a -> m a) -> (Throws e m a -> Throws e m a)
liftT g (Throws m) = Throws (g m)
instance Functor f => Functor (Throws e f) where
fmap f (Throws ma) = Throws (fmap f ma)
instance Applicative f => Applicative (Throws e f) where
pure = Throws . pure
Throws x <*> Throws y = Throws (x <*> y)
Throws x *> Throws y = Throws (x *> y)
Throws x <* Throws y = Throws (x <* y)
instance Alternative f => Alternative (Throws e f) where
empty = Throws empty
Throws x <|> Throws y = Throws (x <|> y)
some (Throws ma) = Throws (some ma)
many (Throws ma) = Throws (many ma)
instance Monad m => Monad (Throws e m) where
return = Throws . return
Throws ma >>= f = Throws (ma >>= hideException . f)
Throws ma >> Throws na = Throws (ma >> na)
fail = Throws . fail
instance MonadPlus m => MonadPlus (Throws e m) where
mzero = Throws mzero
Throws m `mplus` Throws n = Throws (m `mplus` n)
instance MonadIO m => MonadIO (Throws e m) where
liftIO = Throws . liftIO
instance MonadTrans (Throws e) where
lift = Throws
instance (Monoid w, MonadWriter w m) => MonadWriter w (Throws e m) where
writer = Throws . writer
tell = Throws . tell
listen (Throws x) = Throws (listen x)
pass (Throws x) = Throws (pass x)
instance MonadState s m => MonadState s (Throws e m) where
get = Throws get
put = Throws . put
state = Throws . state
instance MonadReader r m => MonadReader r (Throws e m) where
ask = Throws ask
local f (Throws x) = Throws (local f x)
reader = Throws . reader
instance (Monoid w, MonadReader r m, MonadWriter w m, MonadState s m)
=> MonadRWS r w s (Throws e m)
instance MonadError e m => MonadError e (Throws e' m) where
throwError = Throws . throwError
catchError = liftBindLike catchError
instance MonadCont m => MonadCont (Throws e m) where
callCC = liftCCLike callCC
liftHoistLike :: (forall a. m a -> n a) -> Throws e m b -> Throws e' n b
liftHoistLike f x = Throws (f (hideException x))
liftEmbedLike
:: (forall a. m a -> Throws e n a)
-> Throws e' m b -> Throws e n b
liftEmbedLike f x = f (hideException x)
instance MFunctor (Throws e) where
hoist = liftHoistLike
instance MMonad (Throws e) where
embed = liftEmbedLike
instance MonadThrow m => MonadThrow (Throws e m) where
throwM = Throws . throwM
instance MonadCatch m => MonadCatch (Throws e m) where
catch = liftBindLike catch
instance MonadMask m => MonadMask (Throws e m) where
mask = liftMask mask
uninterruptibleMask = liftMask uninterruptibleMask