#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
#endif
#ifndef MIN_VERSION_transformers
#define MIN_VERSION_transformers(x,y,z) 1
#endif
#ifndef MIN_VERSION_mtl
#define MIN_VERSION_mtl(x,y,z) 1
#endif
module Control.Monad.Catch (
MonadThrow(..)
, MonadCatch(..)
, mask_
, uninterruptibleMask_
, catchAll
, catchIOError
, catchJust
, catchIf
, Handler(..), catches
, handle
, handleAll
, handleIOError
, handleJust
, handleIf
, try
, tryJust
, onException
, bracket
, bracket_
, finally
, bracketOnError
, Exception(..)
, SomeException(..)
) where
#if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 706)
import Prelude hiding (foldr)
#else
import Prelude hiding (catch, foldr)
#endif
import Control.Exception (Exception(..), SomeException(..))
import qualified Control.Exception as ControlException
import qualified Control.Monad.Trans.RWS.Lazy as LazyRWS
import qualified Control.Monad.Trans.RWS.Strict as StrictRWS
import qualified Control.Monad.Trans.State.Lazy as LazyS
import qualified Control.Monad.Trans.State.Strict as StrictS
import qualified Control.Monad.Trans.Writer.Lazy as LazyW
import qualified Control.Monad.Trans.Writer.Strict as StrictW
import Control.Monad.Trans.List (ListT)
import Control.Monad.Trans.Maybe (MaybeT)
import Control.Monad.Trans.Error (ErrorT, Error)
import Control.Monad.Trans.Cont (ContT)
import Control.Monad.Trans.Identity
import Control.Monad.Reader as Reader
import Control.Monad.RWS
import Data.Foldable
class Monad m => MonadThrow m where
throwM :: Exception e => e -> m a
class MonadThrow m => MonadCatch m where
catch :: Exception e => m a -> (e -> m a) -> m a
mask :: ((forall a. m a -> m a) -> m b) -> m b
uninterruptibleMask :: ((forall a. m a -> m a) -> m b) -> m b
instance MonadThrow [] where
throwM _ = []
instance MonadThrow Maybe where
throwM _ = Nothing
instance e ~ SomeException => MonadThrow (Either e) where
throwM = Left . toException
instance MonadThrow IO where
throwM = ControlException.throwIO
instance MonadCatch IO where
catch = ControlException.catch
mask = ControlException.mask
uninterruptibleMask = ControlException.uninterruptibleMask
instance MonadThrow m => MonadThrow (IdentityT m) where
throwM e = lift $ throwM e
instance MonadCatch m => MonadCatch (IdentityT m) where
catch (IdentityT m) f = IdentityT (catch m (runIdentityT . f))
mask a = IdentityT $ mask $ \u -> runIdentityT (a $ q u)
where q u = IdentityT . u . runIdentityT
uninterruptibleMask a =
IdentityT $ uninterruptibleMask $ \u -> runIdentityT (a $ q u)
where q u = IdentityT . u . runIdentityT
instance MonadThrow m => MonadThrow (LazyS.StateT s m) where
throwM e = lift $ throwM e
instance MonadCatch m => MonadCatch (LazyS.StateT s m) where
catch = LazyS.liftCatch catch
mask a = LazyS.StateT $ \s -> mask $ \u -> LazyS.runStateT (a $ q u) s
where q u (LazyS.StateT b) = LazyS.StateT (u . b)
uninterruptibleMask a =
LazyS.StateT $ \s -> uninterruptibleMask $ \u -> LazyS.runStateT (a $ q u) s
where q u (LazyS.StateT b) = LazyS.StateT (u . b)
instance MonadThrow m => MonadThrow (StrictS.StateT s m) where
throwM e = lift $ throwM e
instance MonadCatch m => MonadCatch (StrictS.StateT s m) where
catch = StrictS.liftCatch catch
mask a = StrictS.StateT $ \s -> mask $ \u -> StrictS.runStateT (a $ q u) s
where q u (StrictS.StateT b) = StrictS.StateT (u . b)
uninterruptibleMask a =
StrictS.StateT $ \s -> uninterruptibleMask $ \u -> StrictS.runStateT (a $ q u) s
where q u (StrictS.StateT b) = StrictS.StateT (u . b)
instance MonadThrow m => MonadThrow (ReaderT r m) where
throwM e = lift $ throwM e
instance MonadCatch m => MonadCatch (ReaderT r m) where
catch (ReaderT m) c = ReaderT $ \r -> m r `catch` \e -> runReaderT (c e) r
mask a = ReaderT $ \e -> mask $ \u -> Reader.runReaderT (a $ q u) e
where q u (ReaderT b) = ReaderT (u . b)
uninterruptibleMask a =
ReaderT $ \e -> uninterruptibleMask $ \u -> Reader.runReaderT (a $ q u) e
where q u (ReaderT b) = ReaderT (u . b)
instance (MonadThrow m, Monoid w) => MonadThrow (StrictW.WriterT w m) where
throwM e = lift $ throwM e
instance (MonadCatch m, Monoid w) => MonadCatch (StrictW.WriterT w m) where
catch (StrictW.WriterT m) h = StrictW.WriterT $ m `catch ` \e -> StrictW.runWriterT (h e)
mask a = StrictW.WriterT $ mask $ \u -> StrictW.runWriterT (a $ q u)
where q u b = StrictW.WriterT $ u (StrictW.runWriterT b)
uninterruptibleMask a =
StrictW.WriterT $ uninterruptibleMask $ \u -> StrictW.runWriterT (a $ q u)
where q u b = StrictW.WriterT $ u (StrictW.runWriterT b)
instance (MonadThrow m, Monoid w) => MonadThrow (LazyW.WriterT w m) where
throwM e = lift $ throwM e
instance (MonadCatch m, Monoid w) => MonadCatch (LazyW.WriterT w m) where
catch (LazyW.WriterT m) h = LazyW.WriterT $ m `catch ` \e -> LazyW.runWriterT (h e)
mask a = LazyW.WriterT $ mask $ \u -> LazyW.runWriterT (a $ q u)
where q u b = LazyW.WriterT $ u (LazyW.runWriterT b)
uninterruptibleMask a =
LazyW.WriterT $ uninterruptibleMask $ \u -> LazyW.runWriterT (a $ q u)
where q u b = LazyW.WriterT $ u (LazyW.runWriterT b)
instance (MonadThrow m, Monoid w) => MonadThrow (LazyRWS.RWST r w s m) where
throwM e = lift $ throwM e
instance (MonadCatch m, Monoid w) => MonadCatch (LazyRWS.RWST r w s m) where
catch (LazyRWS.RWST m) h = LazyRWS.RWST $ \r s -> m r s `catch` \e -> LazyRWS.runRWST (h e) r s
mask a = LazyRWS.RWST $ \r s -> mask $ \u -> LazyRWS.runRWST (a $ q u) r s
where q u (LazyRWS.RWST b) = LazyRWS.RWST $ \ r s -> u (b r s)
uninterruptibleMask a =
LazyRWS.RWST $ \r s -> uninterruptibleMask $ \u -> LazyRWS.runRWST (a $ q u) r s
where q u (LazyRWS.RWST b) = LazyRWS.RWST $ \ r s -> u (b r s)
instance (MonadThrow m, Monoid w) => MonadThrow (StrictRWS.RWST r w s m) where
throwM e = lift $ throwM e
instance (MonadCatch m, Monoid w) => MonadCatch (StrictRWS.RWST r w s m) where
catch (StrictRWS.RWST m) h = StrictRWS.RWST $ \r s -> m r s `catch` \e -> StrictRWS.runRWST (h e) r s
mask a = StrictRWS.RWST $ \r s -> mask $ \u -> StrictRWS.runRWST (a $ q u) r s
where q u (StrictRWS.RWST b) = StrictRWS.RWST $ \ r s -> u (b r s)
uninterruptibleMask a =
StrictRWS.RWST $ \r s -> uninterruptibleMask $ \u -> StrictRWS.runRWST (a $ q u) r s
where q u (StrictRWS.RWST b) = StrictRWS.RWST $ \ r s -> u (b r s)
instance MonadThrow m => MonadThrow (ListT m) where
throwM = lift . throwM
instance MonadThrow m => MonadThrow (MaybeT m) where
throwM = lift . throwM
instance (Error e, MonadThrow m) => MonadThrow (ErrorT e m) where
throwM = lift . throwM
instance MonadThrow m => MonadThrow (ContT r m) where
throwM = lift . throwM
mask_ :: MonadCatch m => m a -> m a
mask_ io = mask $ \_ -> io
uninterruptibleMask_ :: MonadCatch m => m a -> m a
uninterruptibleMask_ io = uninterruptibleMask $ \_ -> io
catchAll :: MonadCatch m => m a -> (SomeException -> m a) -> m a
catchAll = catch
catchIOError :: MonadCatch m => m a -> (IOError -> m a) -> m a
catchIOError = catch
catchIf :: (MonadCatch m, Exception e) =>
(e -> Bool) -> m a -> (e -> m a) -> m a
catchIf f a b = a `catch` \e -> if f e then b e else throwM e
catchJust :: (MonadCatch m, Exception e) =>
(e -> Maybe b) -> m a -> (b -> m a) -> m a
catchJust f a b = a `catch` \e -> maybe (throwM e) b $ f e
handle :: (MonadCatch m, Exception e) => (e -> m a) -> m a -> m a
handle = flip catch
handleIOError :: MonadCatch m => (IOError -> m a) -> m a -> m a
handleIOError = handle
handleAll :: MonadCatch m => (SomeException -> m a) -> m a -> m a
handleAll = handle
handleIf :: (MonadCatch m, Exception e) => (e -> Bool) -> (e -> m a) -> m a -> m a
handleIf f = flip (catchIf f)
handleJust :: (MonadCatch m, Exception e) => (e -> Maybe b) -> (b -> m a) -> m a -> m a
handleJust f = flip (catchJust f)
try :: (MonadCatch m, Exception e) => m a -> m (Either e a)
try a = catch (Right `liftM` a) (return . Left)
tryJust :: (MonadCatch m, Exception e) =>
(e -> Maybe b) -> m a -> m (Either b a)
tryJust f a = catch (Right `liftM` a) (\e -> maybe (throwM e) (return . Left) (f e))
data Handler m a = forall e . ControlException.Exception e => Handler (e -> m a)
instance Monad m => Functor (Handler m) where
fmap f (Handler h) = Handler (liftM f . h)
catches :: (Foldable f, MonadCatch m) => m a -> f (Handler m a) -> m a
catches a hs = a `catch` handler
where
handler e = foldr probe (throwM e) hs
where
probe (Handler h) xs = maybe xs h (ControlException.fromException e)
onException :: MonadCatch m => m a -> m b -> m a
onException action handler = action `catchAll` \e -> handler >> throwM e
bracket :: MonadCatch m => m a -> (a -> m b) -> (a -> m c) -> m c
bracket acquire release use = mask $ \unmasked -> do
resource <- acquire
result <- unmasked (use resource) `onException` release resource
_ <- release resource
return result
bracket_ :: MonadCatch m => m a -> m b -> m c -> m c
bracket_ before after action = bracket before (const after) (const action)
finally :: MonadCatch m => m a -> m b -> m a
finally action finalizer = bracket_ (return ()) finalizer action
bracketOnError :: MonadCatch m => m a -> (a -> m b) -> (a -> m c) -> m c
bracketOnError acquire release use = mask $ \unmasked -> do
resource <- acquire
unmasked (use resource) `onException` release resource