#ifdef KIND_POLYMORPHIC_TYPEABLE
#endif
module Control.Monad.TaggedException.Internal.Throws
(
Throws(..)
, 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 ((.))
#ifdef KIND_POLYMORPHIC_TYPEABLE
import Data.Typeable (Typeable)
#endif
import GHC.Generics (Generic)
import Control.Monad.IO.Class (MonadIO(liftIO))
import Control.Monad.Trans.Class (MonadTrans(lift))
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
}
deriving
( Generic
#ifdef KIND_POLYMORPHIC_TYPEABLE
, Typeable
#endif
)
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 MFunctor (Throws e) where
hoist f x = Throws (f (hideException x))
instance MMonad (Throws e) where
embed f x = f (hideException x)
instance MonadThrow m => MonadThrow (Throws e m) where
throwM = Throws . throwM
instance MonadCatch m => MonadCatch (Throws e m) where
catch (Throws ma) f = Throws (catch ma (hideException . f))
instance MonadMask m => MonadMask (Throws e m) where
mask = liftMask mask
uninterruptibleMask = liftMask uninterruptibleMask