|
Packit |
1d883e |
{-# LANGUAGE CPP
|
|
Packit |
1d883e |
, NoImplicitPrelude
|
|
Packit |
1d883e |
, ExistentialQuantification
|
|
Packit |
1d883e |
, FlexibleContexts #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,3,0)
|
|
Packit |
1d883e |
{-# LANGUAGE RankNTypes #-} -- for mask
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if __GLASGOW_HASKELL__ >= 702
|
|
Packit |
1d883e |
{-# LANGUAGE Safe #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
{- |
|
|
Packit |
1d883e |
Module : Control.Exception.Lifted
|
|
Packit |
1d883e |
Copyright : Bas van Dijk, Anders Kaseorg
|
|
Packit |
1d883e |
License : BSD-style
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
Maintainer : Bas van Dijk <v.dijk.bas@gmail.com>
|
|
Packit |
1d883e |
Stability : experimental
|
|
Packit |
1d883e |
Portability : non-portable (extended exceptions)
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
This is a wrapped version of "Control.Exception" with types generalized
|
|
Packit |
1d883e |
from 'IO' to all monads in either 'MonadBase' or 'MonadBaseControl'.
|
|
Packit |
1d883e |
-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
module Control.Exception.Lifted
|
|
Packit |
1d883e |
( module Control.Exception
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- * Throwing exceptions
|
|
Packit |
1d883e |
, throwIO, ioError, throwTo
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- * Catching exceptions
|
|
Packit |
1d883e |
-- ** The @catch@ functions
|
|
Packit |
1d883e |
, catch, catches, Handler(..), catchJust
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- ** The @handle@ functions
|
|
Packit |
1d883e |
, handle, handleJust
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- ** The @try@ functions
|
|
Packit |
1d883e |
, try, tryJust
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- ** The @evaluate@ function
|
|
Packit |
1d883e |
, evaluate
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- * Asynchronous Exceptions
|
|
Packit |
1d883e |
-- ** Asynchronous exception control
|
|
Packit |
1d883e |
-- |The following functions allow a thread to control delivery of
|
|
Packit |
1d883e |
-- asynchronous exceptions during a critical region.
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,3,0)
|
|
Packit |
1d883e |
, mask, mask_
|
|
Packit |
1d883e |
, uninterruptibleMask, uninterruptibleMask_
|
|
Packit |
1d883e |
, getMaskingState
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
, allowInterrupt
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
#else
|
|
Packit |
1d883e |
, block, unblock
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if !MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
, blocked
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
-- * Brackets
|
|
Packit |
1d883e |
, bracket, bracket_, bracketOnError
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- * Utilities
|
|
Packit |
1d883e |
, finally, onException
|
|
Packit |
1d883e |
) where
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- Imports
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- from base:
|
|
Packit |
1d883e |
import Prelude ( (.) )
|
|
Packit |
1d883e |
import Data.Function ( ($) )
|
|
Packit |
1d883e |
import Data.Either ( Either(Left, Right), either )
|
|
Packit |
1d883e |
import Data.Maybe ( Maybe )
|
|
Packit |
1d883e |
import Control.Monad ( (>>=), return, liftM )
|
|
Packit |
1d883e |
import System.IO.Error ( IOError )
|
|
Packit |
1d883e |
import System.IO ( IO )
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if __GLASGOW_HASKELL__ < 700
|
|
Packit |
1d883e |
import Control.Monad ( fail )
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
import Control.Exception hiding
|
|
Packit |
1d883e |
( throwIO, ioError, throwTo
|
|
Packit |
1d883e |
, catch, catches, Handler(..), catchJust
|
|
Packit |
1d883e |
, handle, handleJust
|
|
Packit |
1d883e |
, try, tryJust
|
|
Packit |
1d883e |
, evaluate
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,3,0)
|
|
Packit |
1d883e |
, mask, mask_
|
|
Packit |
1d883e |
, uninterruptibleMask, uninterruptibleMask_
|
|
Packit |
1d883e |
, getMaskingState
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
, allowInterrupt
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
#else
|
|
Packit |
1d883e |
, block, unblock
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
#if !MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
, blocked
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
, bracket, bracket_, bracketOnError
|
|
Packit |
1d883e |
, finally, onException
|
|
Packit |
1d883e |
)
|
|
Packit |
1d883e |
import qualified Control.Exception as E
|
|
Packit |
1d883e |
import qualified Control.Concurrent as C
|
|
Packit |
1d883e |
import Control.Concurrent ( ThreadId )
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if !MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
import Data.Bool ( Bool )
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- from transformers-base:
|
|
Packit |
1d883e |
import Control.Monad.Base ( MonadBase, liftBase )
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- from monad-control:
|
|
Packit |
1d883e |
import Control.Monad.Trans.Control ( MonadBaseControl, StM
|
|
Packit |
1d883e |
, liftBaseWith, restoreM
|
|
Packit |
1d883e |
, control, liftBaseOp_
|
|
Packit |
1d883e |
)
|
|
Packit |
1d883e |
#if defined (__HADDOCK__)
|
|
Packit |
1d883e |
import Control.Monad.Trans.Control ( liftBaseOp )
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#include "inlinable.h"
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- * Throwing exceptions
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.throwIO'.
|
|
Packit |
1d883e |
throwIO :: (MonadBase IO m, Exception e) => e -> m a
|
|
Packit |
1d883e |
throwIO = liftBase . E.throwIO
|
|
Packit |
1d883e |
{-# INLINABLE throwIO #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.ioError'.
|
|
Packit |
1d883e |
ioError :: MonadBase IO m => IOError -> m a
|
|
Packit |
1d883e |
ioError = liftBase . E.ioError
|
|
Packit |
1d883e |
{-# INLINABLE ioError #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- | Generalized version of 'C.throwTo'.
|
|
Packit |
1d883e |
throwTo :: (MonadBase IO m, Exception e) => ThreadId -> e -> m ()
|
|
Packit |
1d883e |
throwTo tid e = liftBase $ C.throwTo tid e
|
|
Packit |
1d883e |
{-# INLINABLE throwTo #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- * Catching exceptions
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.catch'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, when the given computation throws an exception any monadic
|
|
Packit |
1d883e |
-- side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
catch :: (MonadBaseControl IO m, Exception e)
|
|
Packit |
1d883e |
=> m a -- ^ The computation to run
|
|
Packit |
1d883e |
-> (e -> m a) -- ^ Handler to invoke if an exception is raised
|
|
Packit |
1d883e |
-> m a
|
|
Packit |
1d883e |
catch a handler = control $ \runInIO ->
|
|
Packit |
1d883e |
E.catch (runInIO a)
|
|
Packit |
1d883e |
(\e -> runInIO $ handler e)
|
|
Packit |
1d883e |
{-# INLINABLE catch #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.catches'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, when the given computation throws an exception any monadic
|
|
Packit |
1d883e |
-- side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
catches :: MonadBaseControl IO m => m a -> [Handler m a] -> m a
|
|
Packit |
1d883e |
catches a handlers = control $ \runInIO ->
|
|
Packit |
1d883e |
E.catches (runInIO a)
|
|
Packit |
1d883e |
[ E.Handler $ \e -> runInIO $ handler e
|
|
Packit |
1d883e |
| Handler handler <- handlers
|
|
Packit |
1d883e |
]
|
|
Packit |
1d883e |
{-# INLINABLE catches #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.Handler'.
|
|
Packit |
1d883e |
data Handler m a = forall e. Exception e => Handler (e -> m a)
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.catchJust'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, when the given computation throws an exception any monadic
|
|
Packit |
1d883e |
-- side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
catchJust :: (MonadBaseControl IO m, Exception e)
|
|
Packit |
1d883e |
=> (e -> Maybe b) -- ^ Predicate to select exceptions
|
|
Packit |
1d883e |
-> m a -- ^ Computation to run
|
|
Packit |
1d883e |
-> (b -> m a) -- ^ Handler
|
|
Packit |
1d883e |
-> m a
|
|
Packit |
1d883e |
catchJust p a handler = control $ \runInIO ->
|
|
Packit |
1d883e |
E.catchJust p
|
|
Packit |
1d883e |
(runInIO a)
|
|
Packit |
1d883e |
(\e -> runInIO (handler e))
|
|
Packit |
1d883e |
{-# INLINABLE catchJust #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- ** The @handle@ functions
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.handle'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, when the given computation throws an exception any monadic
|
|
Packit |
1d883e |
-- side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
handle :: (MonadBaseControl IO m, Exception e) => (e -> m a) -> m a -> m a
|
|
Packit |
1d883e |
handle handler a = control $ \runInIO ->
|
|
Packit |
1d883e |
E.handle (\e -> runInIO (handler e))
|
|
Packit |
1d883e |
(runInIO a)
|
|
Packit |
1d883e |
{-# INLINABLE handle #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.handleJust'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, when the given computation throws an exception any monadic
|
|
Packit |
1d883e |
-- side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
handleJust :: (MonadBaseControl IO m, Exception e)
|
|
Packit |
1d883e |
=> (e -> Maybe b) -> (b -> m a) -> m a -> m a
|
|
Packit |
1d883e |
handleJust p handler a = control $ \runInIO ->
|
|
Packit |
1d883e |
E.handleJust p (\e -> runInIO (handler e))
|
|
Packit |
1d883e |
(runInIO a)
|
|
Packit |
1d883e |
{-# INLINABLE handleJust #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- ** The @try@ functions
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
sequenceEither :: MonadBaseControl IO m => Either e (StM m a) -> m (Either e a)
|
|
Packit |
1d883e |
sequenceEither = either (return . Left) (liftM Right . restoreM)
|
|
Packit |
1d883e |
{-# INLINE sequenceEither #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.try'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, when the given computation throws an exception any monadic
|
|
Packit |
1d883e |
-- side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
try :: (MonadBaseControl IO m, Exception e) => m a -> m (Either e a)
|
|
Packit |
1d883e |
try m = liftBaseWith (\runInIO -> E.try (runInIO m)) >>= sequenceEither
|
|
Packit |
1d883e |
{-# INLINABLE try #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.tryJust'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, when the given computation throws an exception any monadic
|
|
Packit |
1d883e |
-- side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
tryJust :: (MonadBaseControl IO m, Exception e) => (e -> Maybe b) -> m a -> m (Either b a)
|
|
Packit |
1d883e |
tryJust p m = liftBaseWith (\runInIO -> E.tryJust p (runInIO m)) >>= sequenceEither
|
|
Packit |
1d883e |
{-# INLINABLE tryJust #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- ** The @evaluate@ function
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.evaluate'.
|
|
Packit |
1d883e |
evaluate :: MonadBase IO m => a -> m a
|
|
Packit |
1d883e |
evaluate = liftBase . E.evaluate
|
|
Packit |
1d883e |
{-# INLINABLE evaluate #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- ** Asynchronous exception control
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,3,0)
|
|
Packit |
1d883e |
-- |Generalized version of 'E.mask'.
|
|
Packit |
1d883e |
mask :: MonadBaseControl IO m => ((forall a. m a -> m a) -> m b) -> m b
|
|
Packit |
1d883e |
mask f = control $ \runInBase ->
|
|
Packit |
1d883e |
E.mask $ \g -> runInBase $ f $ liftBaseOp_ g
|
|
Packit |
1d883e |
{-# INLINABLE mask #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.mask_'.
|
|
Packit |
1d883e |
mask_ :: MonadBaseControl IO m => m a -> m a
|
|
Packit |
1d883e |
mask_ = liftBaseOp_ E.mask_
|
|
Packit |
1d883e |
{-# INLINABLE mask_ #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.uninterruptibleMask'.
|
|
Packit |
1d883e |
uninterruptibleMask
|
|
Packit |
1d883e |
:: MonadBaseControl IO m => ((forall a. m a -> m a) -> m b) -> m b
|
|
Packit |
1d883e |
uninterruptibleMask f =
|
|
Packit |
1d883e |
control $ \runInBase ->
|
|
Packit |
1d883e |
E.uninterruptibleMask $ \g -> runInBase $ f $ liftBaseOp_ g
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
{-# INLINABLE uninterruptibleMask #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.uninterruptibleMask_'.
|
|
Packit |
1d883e |
uninterruptibleMask_ :: MonadBaseControl IO m => m a -> m a
|
|
Packit |
1d883e |
uninterruptibleMask_ = liftBaseOp_ E.uninterruptibleMask_
|
|
Packit |
1d883e |
{-# INLINABLE uninterruptibleMask_ #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.getMaskingState'.
|
|
Packit |
1d883e |
getMaskingState :: MonadBase IO m => m MaskingState
|
|
Packit |
1d883e |
getMaskingState = liftBase E.getMaskingState
|
|
Packit |
1d883e |
{-# INLINABLE getMaskingState #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
-- |Generalized version of 'E.allowInterrupt'.
|
|
Packit |
1d883e |
allowInterrupt :: MonadBase IO m => m ()
|
|
Packit |
1d883e |
allowInterrupt = liftBase E.allowInterrupt
|
|
Packit |
1d883e |
{-# INLINABLE allowInterrupt #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
#else
|
|
Packit |
1d883e |
-- |Generalized version of 'E.block'.
|
|
Packit |
1d883e |
block :: MonadBaseControl IO m => m a -> m a
|
|
Packit |
1d883e |
block = liftBaseOp_ E.block
|
|
Packit |
1d883e |
{-# INLINABLE block #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.unblock'.
|
|
Packit |
1d883e |
unblock :: MonadBaseControl IO m => m a -> m a
|
|
Packit |
1d883e |
unblock = liftBaseOp_ E.unblock
|
|
Packit |
1d883e |
{-# INLINABLE unblock #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
#if !MIN_VERSION_base(4,4,0)
|
|
Packit |
1d883e |
-- | Generalized version of 'E.blocked'.
|
|
Packit |
1d883e |
-- returns @True@ if asynchronous exceptions are blocked in the
|
|
Packit |
1d883e |
-- current thread.
|
|
Packit |
1d883e |
blocked :: MonadBase IO m => m Bool
|
|
Packit |
1d883e |
blocked = liftBase E.blocked
|
|
Packit |
1d883e |
{-# INLINABLE blocked #-}
|
|
Packit |
1d883e |
#endif
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- * Brackets
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.bracket'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note:
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- * When the \"acquire\" or \"release\" computations throw exceptions
|
|
Packit |
1d883e |
-- any monadic side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- * When the \"in-between\" computation throws an exception any
|
|
Packit |
1d883e |
-- monadic side effects in @m@ produced by that computation will be
|
|
Packit |
1d883e |
-- discarded but the side effects of the \"acquire\" or \"release\"
|
|
Packit |
1d883e |
-- computations will be retained.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- * Also, any monadic side effects in @m@ of the \"release\"
|
|
Packit |
1d883e |
-- computation will be discarded; it is run only for its side
|
|
Packit |
1d883e |
-- effects in @IO@.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that when your @acquire@ and @release@ computations are of type 'IO'
|
|
Packit |
1d883e |
-- it will be more efficient to write:
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- @'liftBaseOp' ('E.bracket' acquire release)@
|
|
Packit |
1d883e |
bracket :: MonadBaseControl IO m
|
|
Packit |
1d883e |
=> m a -- ^ computation to run first (\"acquire resource\")
|
|
Packit |
1d883e |
-> (a -> m b) -- ^ computation to run last (\"release resource\")
|
|
Packit |
1d883e |
-> (a -> m c) -- ^ computation to run in-between
|
|
Packit |
1d883e |
-> m c
|
|
Packit |
1d883e |
bracket before after thing = control $ \runInIO ->
|
|
Packit |
1d883e |
E.bracket (runInIO before)
|
|
Packit |
1d883e |
(\st -> runInIO $ restoreM st >>= after)
|
|
Packit |
1d883e |
(\st -> runInIO $ restoreM st >>= thing)
|
|
Packit |
1d883e |
{-# INLINABLE bracket #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.bracket_'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note any monadic side effects in @m@ of /both/ the \"acquire\" and
|
|
Packit |
1d883e |
-- \"release\" computations will be discarded. To keep the monadic
|
|
Packit |
1d883e |
-- side effects of the \"acquire\" computation, use 'bracket' with
|
|
Packit |
1d883e |
-- constant functions instead.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that when your @acquire@ and @release@ computations are of type 'IO'
|
|
Packit |
1d883e |
-- it will be more efficient to write:
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- @'liftBaseOp_' ('E.bracket_' acquire release)@
|
|
Packit |
1d883e |
bracket_ :: MonadBaseControl IO m
|
|
Packit |
1d883e |
=> m a -- ^ computation to run first (\"acquire resource\")
|
|
Packit |
1d883e |
-> m b -- ^ computation to run last (\"release resource\")
|
|
Packit |
1d883e |
-> m c -- ^ computation to run in-between
|
|
Packit |
1d883e |
-> m c
|
|
Packit |
1d883e |
bracket_ before after thing = control $ \runInIO ->
|
|
Packit |
1d883e |
E.bracket_ (runInIO before)
|
|
Packit |
1d883e |
(runInIO after)
|
|
Packit |
1d883e |
(runInIO thing)
|
|
Packit |
1d883e |
{-# INLINABLE bracket_ #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.bracketOnError'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note:
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- * When the \"acquire\" or \"release\" computations throw exceptions
|
|
Packit |
1d883e |
-- any monadic side effects in @m@ will be discarded.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- * When the \"in-between\" computation throws an exception any
|
|
Packit |
1d883e |
-- monadic side effects in @m@ produced by that computation will be
|
|
Packit |
1d883e |
-- discarded but the side effects of the \"acquire\" computation
|
|
Packit |
1d883e |
-- will be retained.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- * Also, any monadic side effects in @m@ of the \"release\"
|
|
Packit |
1d883e |
-- computation will be discarded; it is run only for its side
|
|
Packit |
1d883e |
-- effects in @IO@.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note that when your @acquire@ and @release@ computations are of
|
|
Packit |
1d883e |
-- type 'IO' it will be more efficient to write:
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- @'liftBaseOp' ('E.bracketOnError' acquire release)@
|
|
Packit |
1d883e |
bracketOnError :: MonadBaseControl IO m
|
|
Packit |
1d883e |
=> m a -- ^ computation to run first (\"acquire resource\")
|
|
Packit |
1d883e |
-> (a -> m b) -- ^ computation to run last (\"release resource\")
|
|
Packit |
1d883e |
-> (a -> m c) -- ^ computation to run in-between
|
|
Packit |
1d883e |
-> m c
|
|
Packit |
1d883e |
bracketOnError before after thing =
|
|
Packit |
1d883e |
control $ \runInIO ->
|
|
Packit |
1d883e |
E.bracketOnError (runInIO before)
|
|
Packit |
1d883e |
(\st -> runInIO $ restoreM st >>= after)
|
|
Packit |
1d883e |
(\st -> runInIO $ restoreM st >>= thing)
|
|
Packit |
1d883e |
{-# INLINABLE bracketOnError #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
-- * Utilities
|
|
Packit |
1d883e |
--------------------------------------------------------------------------------
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.finally'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, any monadic side effects in @m@ of the \"afterward\"
|
|
Packit |
1d883e |
-- computation will be discarded.
|
|
Packit |
1d883e |
finally :: MonadBaseControl IO m
|
|
Packit |
1d883e |
=> m a -- ^ computation to run first
|
|
Packit |
1d883e |
-> m b -- ^ computation to run afterward (even if an exception was raised)
|
|
Packit |
1d883e |
-> m a
|
|
Packit |
1d883e |
finally a sequel = control $ \runInIO ->
|
|
Packit |
1d883e |
E.finally (runInIO a)
|
|
Packit |
1d883e |
(runInIO sequel)
|
|
Packit |
1d883e |
{-# INLINABLE finally #-}
|
|
Packit |
1d883e |
|
|
Packit |
1d883e |
-- |Generalized version of 'E.onException'.
|
|
Packit |
1d883e |
--
|
|
Packit |
1d883e |
-- Note, any monadic side effects in @m@ of the \"afterward\"
|
|
Packit |
1d883e |
-- computation will be discarded.
|
|
Packit |
1d883e |
onException :: MonadBaseControl IO m => m a -> m b -> m a
|
|
Packit |
1d883e |
onException m what = control $ \runInIO ->
|
|
Packit |
1d883e |
E.onException (runInIO m)
|
|
Packit |
1d883e |
(runInIO what)
|
|
Packit |
1d883e |
{-# INLINABLE onException #-}
|