{-# LANGUAGE CPP #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeFamilies #-}
#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Trustworthy #-}
#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
{-# OPTIONS_GHC -fno-warn-deprecations #-}
module Control.Monad.Catch (
MonadThrow(..)
, MonadCatch(..)
, MonadMask(..)
, ExitCase(..)
, mask_
, uninterruptibleMask_
, catchAll
, catchIOError
, catchJust
, catchIf
, Handler(..), catches
, handle
, handleAll
, handleIOError
, handleJust
, handleIf
, try
, tryJust
, onException
, onError
, bracket
, bracket_
, finally
, bracketOnError
, Exception(..)
, SomeException(..)
) where
import Control.Exception (Exception(..), SomeException(..))
import qualified Control.Exception as ControlException
import qualified Control.Monad.STM as STM
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.ST (ST)
import Control.Monad.STM (STM)
import Control.Monad.Trans.List (ListT(..), runListT)
import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
import Control.Monad.Trans.Error (ErrorT(..), Error, runErrorT)
import Control.Monad.Trans.Except (ExceptT(..), runExceptT)
import Control.Monad.Trans.Cont (ContT)
import Control.Monad.Trans.Identity
import Control.Monad.Reader as Reader
import Language.Haskell.TH.Syntax (Q)
#if MIN_VERSION_base(4,4,0)
import Control.Monad.ST.Unsafe (unsafeIOToST)
#else
import Control.Monad.ST (unsafeIOToST)
#endif
#if __GLASGOW_HASKELL__ < 706
import Prelude hiding (catch, foldr)
import Data.Foldable
import Data.Monoid
#elif __GLASGOW_HASKELL__ < 710
import Prelude hiding (foldr)
import Data.Foldable
import Data.Monoid
#endif
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
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
class MonadCatch m => MonadMask m where
mask :: ((forall a. m a -> m a) -> m b) -> m b
uninterruptibleMask :: ((forall a. m a -> m a) -> m b) -> m b
generalBracket
:: m a
-> (a -> ExitCase b -> m c)
-> (a -> m b)
-> m (b, c)
data ExitCase a
= ExitCaseSuccess a
| ExitCaseException SomeException
| ExitCaseAbort
deriving Show
instance MonadThrow [] where
throwM _ = []
instance MonadThrow Maybe where
throwM _ = Nothing
instance MonadThrow Q where
throwM = fail . show
instance MonadThrow IO where
throwM = ControlException.throwIO
instance MonadCatch IO where
catch = ControlException.catch
instance MonadMask IO where
mask = ControlException.mask
uninterruptibleMask = ControlException.uninterruptibleMask
generalBracket acquire release use = mask $ \unmasked -> do
resource <- acquire
b <- unmasked (use resource) `catch` \e -> do
_ <- release resource (ExitCaseException e)
throwM e
c <- release resource (ExitCaseSuccess b)
return (b, c)
instance MonadThrow (ST s) where
throwM = unsafeIOToST . ControlException.throwIO
instance MonadThrow STM where
throwM = STM.throwSTM
instance MonadCatch STM where
catch = STM.catchSTM
instance e ~ SomeException => MonadThrow (Either e) where
throwM = Left . toException
instance e ~ SomeException => MonadCatch (Either e) where
catch (Left e) f =
case fromException e of
Nothing -> Left e
Just e' -> f e'
catch x@(Right _) _ = x
instance e ~ SomeException => MonadMask (Either e) where
mask f = f id
uninterruptibleMask f = f id
generalBracket acquire release use =
case acquire of
Left e -> Left e
Right resource ->
case use resource of
Left e -> release resource (ExitCaseException e) >> Left e
Right b -> do
c <- release resource (ExitCaseSuccess b)
return (b, c)
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))
instance MonadMask m => MonadMask (IdentityT m) where
mask a = IdentityT $ mask $ \u -> runIdentityT (a $ q u)
where q :: (m a -> m a) -> IdentityT m a -> IdentityT m a
q u = IdentityT . u . runIdentityT
uninterruptibleMask a =
IdentityT $ uninterruptibleMask $ \u -> runIdentityT (a $ q u)
where q :: (m a -> m a) -> IdentityT m a -> IdentityT m a
q u = IdentityT . u . runIdentityT
generalBracket acquire release use = IdentityT $
generalBracket
(runIdentityT acquire)
(\resource exitCase -> runIdentityT (release resource exitCase))
(\resource -> runIdentityT (use resource))
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
instance MonadMask m => MonadMask (LazyS.StateT s m) where
mask a = LazyS.StateT $ \s -> mask $ \u -> LazyS.runStateT (a $ q u) s
where q :: (m (a, s) -> m (a, s)) -> LazyS.StateT s m a -> LazyS.StateT s m a
q u (LazyS.StateT b) = LazyS.StateT (u . b)
uninterruptibleMask a =
LazyS.StateT $ \s -> uninterruptibleMask $ \u -> LazyS.runStateT (a $ q u) s
where q :: (m (a, s) -> m (a, s)) -> LazyS.StateT s m a -> LazyS.StateT s m a
q u (LazyS.StateT b) = LazyS.StateT (u . b)
generalBracket acquire release use = LazyS.StateT $ \s0 -> do
((b, _s2), (c, s3)) <- generalBracket
(LazyS.runStateT acquire s0)
(\(resource, s1) exitCase -> case exitCase of
ExitCaseSuccess (b, s2) -> LazyS.runStateT (release resource (ExitCaseSuccess b)) s2
ExitCaseException e -> LazyS.runStateT (release resource (ExitCaseException e)) s1
ExitCaseAbort -> LazyS.runStateT (release resource ExitCaseAbort) s1)
(\(resource, s1) -> LazyS.runStateT (use resource) s1)
return ((b, c), s3)
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
instance MonadMask m => MonadMask (StrictS.StateT s m) where
mask a = StrictS.StateT $ \s -> mask $ \u -> StrictS.runStateT (a $ q u) s
where q :: (m (a, s) -> m (a, s)) -> StrictS.StateT s m a -> StrictS.StateT s m a
q u (StrictS.StateT b) = StrictS.StateT (u . b)
uninterruptibleMask a =
StrictS.StateT $ \s -> uninterruptibleMask $ \u -> StrictS.runStateT (a $ q u) s
where q :: (m (a, s) -> m (a, s)) -> StrictS.StateT s m a -> StrictS.StateT s m a
q u (StrictS.StateT b) = StrictS.StateT (u . b)
generalBracket acquire release use = StrictS.StateT $ \s0 -> do
((b, _s2), (c, s3)) <- generalBracket
(StrictS.runStateT acquire s0)
(\(resource, s1) exitCase -> case exitCase of
ExitCaseSuccess (b, s2) -> StrictS.runStateT (release resource (ExitCaseSuccess b)) s2
ExitCaseException e -> StrictS.runStateT (release resource (ExitCaseException e)) s1
ExitCaseAbort -> StrictS.runStateT (release resource ExitCaseAbort) s1)
(\(resource, s1) -> StrictS.runStateT (use resource) s1)
return ((b, c), s3)
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
instance MonadMask m => MonadMask (ReaderT r m) where
mask a = ReaderT $ \e -> mask $ \u -> runReaderT (a $ q u) e
where q :: (m a -> m a) -> ReaderT e m a -> ReaderT e m a
q u (ReaderT b) = ReaderT (u . b)
uninterruptibleMask a =
ReaderT $ \e -> uninterruptibleMask $ \u -> runReaderT (a $ q u) e
where q :: (m a -> m a) -> ReaderT e m a -> ReaderT e m a
q u (ReaderT b) = ReaderT (u . b)
generalBracket acquire release use = ReaderT $ \r ->
generalBracket
(runReaderT acquire r)
(\resource exitCase -> runReaderT (release resource exitCase) r)
(\resource -> runReaderT (use resource) r)
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)
instance (MonadMask m, Monoid w) => MonadMask (StrictW.WriterT w m) where
mask a = StrictW.WriterT $ mask $ \u -> StrictW.runWriterT (a $ q u)
where q :: (m (a, w) -> m (a, w)) -> StrictW.WriterT w m a -> StrictW.WriterT w m a
q u b = StrictW.WriterT $ u (StrictW.runWriterT b)
uninterruptibleMask a =
StrictW.WriterT $ uninterruptibleMask $ \u -> StrictW.runWriterT (a $ q u)
where q :: (m (a, w) -> m (a, w)) -> StrictW.WriterT w m a -> StrictW.WriterT w m a
q u b = StrictW.WriterT $ u (StrictW.runWriterT b)
generalBracket acquire release use = StrictW.WriterT $ do
((b, _w12), (c, w123)) <- generalBracket
(StrictW.runWriterT acquire)
(\(resource, w1) exitCase -> case exitCase of
ExitCaseSuccess (b, w12) -> do
(c, w3) <- StrictW.runWriterT (release resource (ExitCaseSuccess b))
return (c, mappend w12 w3)
ExitCaseException e -> do
(c, w3) <- StrictW.runWriterT (release resource (ExitCaseException e))
return (c, mappend w1 w3)
ExitCaseAbort -> do
(c, w3) <- StrictW.runWriterT (release resource ExitCaseAbort)
return (c, mappend w1 w3))
(\(resource, w1) -> do
(a, w2) <- StrictW.runWriterT (use resource)
return (a, mappend w1 w2))
return ((b, c), w123)
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)
instance (MonadMask m, Monoid w) => MonadMask (LazyW.WriterT w m) where
mask a = LazyW.WriterT $ mask $ \u -> LazyW.runWriterT (a $ q u)
where q :: (m (a, w) -> m (a, w)) -> LazyW.WriterT w m a -> LazyW.WriterT w m a
q u b = LazyW.WriterT $ u (LazyW.runWriterT b)
uninterruptibleMask a =
LazyW.WriterT $ uninterruptibleMask $ \u -> LazyW.runWriterT (a $ q u)
where q :: (m (a, w) -> m (a, w)) -> LazyW.WriterT w m a -> LazyW.WriterT w m a
q u b = LazyW.WriterT $ u (LazyW.runWriterT b)
generalBracket acquire release use = LazyW.WriterT $ do
((b, _w12), (c, w123)) <- generalBracket
(LazyW.runWriterT acquire)
(\(resource, w1) exitCase -> case exitCase of
ExitCaseSuccess (b, w12) -> do
(c, w3) <- LazyW.runWriterT (release resource (ExitCaseSuccess b))
return (c, mappend w12 w3)
ExitCaseException e -> do
(c, w3) <- LazyW.runWriterT (release resource (ExitCaseException e))
return (c, mappend w1 w3)
ExitCaseAbort -> do
(c, w3) <- LazyW.runWriterT (release resource ExitCaseAbort)
return (c, mappend w1 w3))
(\(resource, w1) -> do
(a, w2) <- LazyW.runWriterT (use resource)
return (a, mappend w1 w2))
return ((b, c), w123)
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
instance (MonadMask m, Monoid w) => MonadMask (LazyRWS.RWST r w s m) where
mask a = LazyRWS.RWST $ \r s -> mask $ \u -> LazyRWS.runRWST (a $ q u) r s
where q :: (m (a, s, w) -> m (a, s, w)) -> LazyRWS.RWST r w s m a -> LazyRWS.RWST r w s m a
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 :: (m (a, s, w) -> m (a, s, w)) -> LazyRWS.RWST r w s m a -> LazyRWS.RWST r w s m a
q u (LazyRWS.RWST b) = LazyRWS.RWST $ \ r s -> u (b r s)
generalBracket acquire release use = LazyRWS.RWST $ \r s0 -> do
((b, _s2, _w12), (c, s3, w123)) <- generalBracket
(LazyRWS.runRWST acquire r s0)
(\(resource, s1, w1) exitCase -> case exitCase of
ExitCaseSuccess (b, s2, w12) -> do
(c, s3, w3) <- LazyRWS.runRWST (release resource (ExitCaseSuccess b)) r s2
return (c, s3, mappend w12 w3)
ExitCaseException e -> do
(c, s3, w3) <- LazyRWS.runRWST (release resource (ExitCaseException e)) r s1
return (c, s3, mappend w1 w3)
ExitCaseAbort -> do
(c, s3, w3) <- LazyRWS.runRWST (release resource ExitCaseAbort) r s1
return (c, s3, mappend w1 w3))
(\(resource, s1, w1) -> do
(a, s2, w2) <- LazyRWS.runRWST (use resource) r s1
return (a, s2, mappend w1 w2))
return ((b, c), s3, w123)
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
instance (MonadMask m, Monoid w) => MonadMask (StrictRWS.RWST r w s m) where
mask a = StrictRWS.RWST $ \r s -> mask $ \u -> StrictRWS.runRWST (a $ q u) r s
where q :: (m (a, s, w) -> m (a, s, w)) -> StrictRWS.RWST r w s m a -> StrictRWS.RWST r w s m a
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 :: (m (a, s, w) -> m (a, s, w)) -> StrictRWS.RWST r w s m a -> StrictRWS.RWST r w s m a
q u (StrictRWS.RWST b) = StrictRWS.RWST $ \ r s -> u (b r s)
generalBracket acquire release use = StrictRWS.RWST $ \r s0 -> do
((b, _s2, _w12), (c, s3, w123)) <- generalBracket
(StrictRWS.runRWST acquire r s0)
(\(resource, s1, w1) exitCase -> case exitCase of
ExitCaseSuccess (b, s2, w12) -> do
(c, s3, w3) <- StrictRWS.runRWST (release resource (ExitCaseSuccess b)) r s2
return (c, s3, mappend w12 w3)
ExitCaseException e -> do
(c, s3, w3) <- StrictRWS.runRWST (release resource (ExitCaseException e)) r s1
return (c, s3, mappend w1 w3)
ExitCaseAbort -> do
(c, s3, w3) <- StrictRWS.runRWST (release resource ExitCaseAbort) r s1
return (c, s3, mappend w1 w3))
(\(resource, s1, w1) -> do
(a, s2, w2) <- StrictRWS.runRWST (use resource) r s1
return (a, s2, mappend w1 w2))
return ((b, c), s3, w123)
instance MonadThrow m => MonadThrow (ListT m) where
throwM = lift . throwM
instance MonadCatch m => MonadCatch (ListT m) where
catch (ListT m) f = ListT $ catch m (runListT . f)
instance MonadThrow m => MonadThrow (MaybeT m) where
throwM = lift . throwM
instance MonadCatch m => MonadCatch (MaybeT m) where
catch (MaybeT m) f = MaybeT $ catch m (runMaybeT . f)
instance MonadMask m => MonadMask (MaybeT m) where
mask f = MaybeT $ mask $ \u -> runMaybeT $ f (q u)
where
q :: (m (Maybe a) -> m (Maybe a))
-> MaybeT m a -> MaybeT m a
q u (MaybeT b) = MaybeT (u b)
uninterruptibleMask f = MaybeT $ uninterruptibleMask $ \u -> runMaybeT $ f (q u)
where
q :: (m (Maybe a) -> m (Maybe a))
-> MaybeT m a -> MaybeT m a
q u (MaybeT b) = MaybeT (u b)
generalBracket acquire release use = MaybeT $ do
(eb, ec) <- generalBracket
(runMaybeT acquire)
(\resourceMay exitCase -> case resourceMay of
Nothing -> return Nothing
Just resource -> case exitCase of
ExitCaseSuccess (Just b) -> runMaybeT (release resource (ExitCaseSuccess b))
ExitCaseException e -> runMaybeT (release resource (ExitCaseException e))
_ -> runMaybeT (release resource ExitCaseAbort))
(\resourceMay -> case resourceMay of
Nothing -> return Nothing
Just resource -> runMaybeT (use resource))
return ((,) <$> eb <*> ec)
instance (Error e, MonadThrow m) => MonadThrow (ErrorT e m) where
throwM = lift . throwM
instance (Error e, MonadCatch m) => MonadCatch (ErrorT e m) where
catch (ErrorT m) f = ErrorT $ catch m (runErrorT . f)
instance (Error e, MonadMask m) => MonadMask (ErrorT e m) where
mask f = ErrorT $ mask $ \u -> runErrorT $ f (q u)
where
q :: (m (Either e a) -> m (Either e a))
-> ErrorT e m a -> ErrorT e m a
q u (ErrorT b) = ErrorT (u b)
uninterruptibleMask f = ErrorT $ uninterruptibleMask $ \u -> runErrorT $ f (q u)
where
q :: (m (Either e a) -> m (Either e a))
-> ErrorT e m a -> ErrorT e m a
q u (ErrorT b) = ErrorT (u b)
generalBracket acquire release use = ErrorT $ do
(eb, ec) <- generalBracket
(runErrorT acquire)
(\eresource exitCase -> case eresource of
Left e -> return (Left e)
Right resource -> case exitCase of
ExitCaseSuccess (Right b) -> runErrorT (release resource (ExitCaseSuccess b))
ExitCaseException e -> runErrorT (release resource (ExitCaseException e))
_ -> runErrorT (release resource ExitCaseAbort))
(either (return . Left) (runErrorT . use))
return $ do
c <- ec
b <- eb
return (b, c)
instance MonadThrow m => MonadThrow (ExceptT e m) where
throwM = lift . throwM
instance MonadCatch m => MonadCatch (ExceptT e m) where
catch (ExceptT m) f = ExceptT $ catch m (runExceptT . f)
instance MonadMask m => MonadMask (ExceptT e m) where
mask f = ExceptT $ mask $ \u -> runExceptT $ f (q u)
where
q :: (m (Either e a) -> m (Either e a))
-> ExceptT e m a -> ExceptT e m a
q u (ExceptT b) = ExceptT (u b)
uninterruptibleMask f = ExceptT $ uninterruptibleMask $ \u -> runExceptT $ f (q u)
where
q :: (m (Either e a) -> m (Either e a))
-> ExceptT e m a -> ExceptT e m a
q u (ExceptT b) = ExceptT (u b)
generalBracket acquire release use = ExceptT $ do
(eb, ec) <- generalBracket
(runExceptT acquire)
(\eresource exitCase -> case eresource of
Left e -> return (Left e)
Right resource -> case exitCase of
ExitCaseSuccess (Right b) -> runExceptT (release resource (ExitCaseSuccess b))
ExitCaseException e -> runExceptT (release resource (ExitCaseException e))
_ -> runExceptT (release resource ExitCaseAbort))
(either (return . Left) (runExceptT . use))
return $ do
c <- ec
b <- eb
return (b, c)
instance MonadThrow m => MonadThrow (ContT r m) where
throwM = lift . throwM
mask_ :: MonadMask m => m a -> m a
mask_ io = mask $ \_ -> io
uninterruptibleMask_ :: MonadMask 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
{-# INLINE handle #-}
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)
{-# INLINE handleJust #-}
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
onError :: MonadMask m => m a -> m b -> m a
onError action handler = bracketOnError (return ()) (const handler) (const action)
bracket :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
bracket acquire release = liftM fst . generalBracket
acquire
(\a _exitCase -> release a)
bracket_ :: MonadMask m => m a -> m c -> m b -> m b
bracket_ before after action = bracket before (const after) (const action)
finally :: MonadMask m => m a -> m b -> m a
finally action finalizer = bracket_ (return ()) finalizer action
bracketOnError :: MonadMask m => m a -> (a -> m c) -> (a -> m b) -> m b
bracketOnError acquire release = liftM fst . generalBracket
acquire
(\a exitCase -> case exitCase of
ExitCaseSuccess _ -> return ()
_ -> do
_ <- release a
return ())