{-# LANGUAGE CPP #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} #ifdef KIND_POLYMORPHIC_TYPEABLE {-# LANGUAGE DeriveDataTypeable #-} #endif #ifdef GHC_GENERICS {-# LANGUAGE DeriveGeneric #-} #endif -- Following extensions are required for mtl type classes: {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} -- Originally there was a separate package that defined these instances and it -- used orphan instances. -- | -- Module: $HEADER$ -- Description: Data type for associating monadic value with phantom type. -- Copyright: (c) 2009-2016, Peter Trško -- License: BSD3 -- -- Maintainer: peter.trsko@gmail.com -- Stability: stable -- Portability: CPP, NoImplicitPrelude, PolyKinds, RankNTypes, -- DeriveDataTypeable, DeriveGeneric -- -- Data type for associating monadic value with phantom type. In case of this -- library it will always be associated with a type of exception it may throw. 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 #if __GLASGOW_HASKELL__ >= 710 , Generic1 #endif ) #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)) -- | Exception tag. newtype Throws e m a = Throws { hideException :: m a -- ^ Hide one exception. } #ifdef GHC_GENERICS -- GHC Generics were introduced earlier then polykinded Typeable. deriving ( Generic #if __GLASGOW_HASKELL__ >= 710 , Generic1 #endif #ifdef KIND_POLYMORPHIC_TYPEABLE , Typeable #endif ) #endif -- | Lift operations with type similar to monadic bind. In example: -- -- @ -- ('Control.Monad.>>=') :: 'Control.Monad.Monad' m => m a -> (a -> m b) -> m b -- @ -- -- @ -- 'Prelude.catch' -- :: 'System.IO.IO' a -- -> ('Control.Exception.IOError' -> 'System.IO.IO' a) -- -> 'System.IO.IO' a -- @ -- -- @ -- 'Control.Exception.catch' -- :: 'Control.Exception.Exception' e -- => 'System.IO.IO' a -> (e -> 'System.IO.IO' a) -> 'System.IO.IO' a -- @ -- -- Since @1.2.0.0@. 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)) {-# INLINE liftBindLike #-} -- | Lift operation with type similar to 'Control.Monad.Cont.Class.liftCC': -- -- @ -- 'Control.Monad.Cont.Class.liftCC' -- :: 'Control.Monad.Monad' m => ((a -> m b) -> m a) -> m a -- @ -- -- Since @2.1.0.0@ 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)))) -- f :: ((a -> m b) -> m c) -> m d -- g :: (a -> Throws e m b) -> Throws e m c -- \h -> hideException (g (Throws . h) :: (a -> m b) -> m c {-# INLINE liftCCLike #-} -- | Lift operation similar to the one of 'Control.Exception.mask'. 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) {-# INLINABLE liftMask #-} -- {{{ Instances -------------------------------------------------------------- instance Functor f => Functor (Throws e f) where -- (a -> b) -> Throws e f a -> Throws e f b 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) -- {{{ Instances: transformers ------------------------------------------------ instance MonadIO m => MonadIO (Throws e m) where liftIO = Throws . liftIO instance MonadTrans (Throws e) where lift = Throws -- }}} Instances: transformers ------------------------------------------------ -- {{{ Instances: mtl --------------------------------------------------------- -- | Since @2.1.0.0@ 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) -- | Since @2.1.0.0@ instance MonadState s m => MonadState s (Throws e m) where get = Throws get put = Throws . put state = Throws . state -- | Since @2.1.0.0@ instance MonadReader r m => MonadReader r (Throws e m) where ask = Throws ask local f (Throws x) = Throws (local f x) reader = Throws . reader -- | Since @2.1.0.0@ instance (Monoid w, MonadReader r m, MonadWriter w m, MonadState s m) => MonadRWS r w s (Throws e m) -- | Since @2.1.0.0@ instance MonadError e m => MonadError e (Throws e' m) where throwError = Throws . throwError catchError = liftBindLike catchError -- | Since @2.1.0.0@ instance MonadCont m => MonadCont (Throws e m) where -- :: ((a -> Throws e m b) -> Throws e m a) -> Throws e m a callCC = liftCCLike callCC -- {{{ Instances: mtl --------------------------------------------------------- -- {{{ Instances: mmorph ------------------------------------------------------ -- | Generalized form of 'embed' from @instance 'MFunctor' ('Throws' e)@. -- -- Since @2.1.0.0@ liftHoistLike :: (forall a. m a -> n a) -> Throws e m b -> Throws e' n b liftHoistLike f x = Throws (f (hideException x)) {-# INLINE liftHoistLike #-} -- | Generalized form of 'embed' from @instance 'MMonad' ('Throws' e)@. -- -- Since @2.1.0.0@ liftEmbedLike :: (forall a. m a -> Throws e n a) -> Throws e' m b -> Throws e n b liftEmbedLike f x = f (hideException x) {-# INLINE liftEmbedLike #-} -- | Since @1.2.0.0@. instance MFunctor (Throws e) where -- :: Monad m => (forall a. m a -> n a) -> Throws e m b -> Throws e n b hoist = liftHoistLike -- | Since @1.2.0.0@. instance MMonad (Throws e) where -- :: Monad n -- => (forall a. m a -> Throws e n a) -- -> Throws e m b -> Throws e n b embed = liftEmbedLike -- }}} Instances: mmorph ------------------------------------------------------ -- {{{ Instances: exceptions -------------------------------------------------- -- | Since @2.0.0.0@. instance MonadThrow m => MonadThrow (Throws e m) where -- throwM :: Exception e' => e' -> Throws m a throwM = Throws . throwM -- | Since @2.0.0.0@. instance MonadCatch m => MonadCatch (Throws e m) where -- :: Exception e' => Throws m a -> (e' -> Throws m a) -> Throws m a catch = liftBindLike catch -- | Since @2.0.0.0@. instance MonadMask m => MonadMask (Throws e m) where -- :: ((forall a. Throws e m a -> Throws e m a) -> Throws e m b) -- -> Throws e m b mask = liftMask mask -- :: ((forall a. Throws e m a -> Throws e m a) -> Throws e m b) -- -> Throws e m b uninterruptibleMask = liftMask uninterruptibleMask -- }}} Instances: exceptions -------------------------------------------------- -- }}} Instances --------------------------------------------------------------