{-# LANGUAGE CPP
, NoImplicitPrelude
, ExistentialQuantification
, FlexibleContexts
, ImpredicativeTypes #-}
#if MIN_VERSION_base(4,3,0)
{-# LANGUAGE RankNTypes #-}
#endif
#if __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Trustworthy #-}
#endif
module Control.Exception.Lifted
( module Control.Exception
, throwIO, ioError, throwTo
, catch, catches, Handler(..), catchJust
, handle, handleJust
, try, tryJust
, evaluate
#if MIN_VERSION_base(4,3,0)
, mask, mask_
, uninterruptibleMask, uninterruptibleMask_
, getMaskingState
#if MIN_VERSION_base(4,4,0)
, allowInterrupt
#endif
#else
, block, unblock
#endif
#if !MIN_VERSION_base(4,4,0)
, blocked
#endif
, bracket, bracket_, bracketOnError
, finally, onException
) where
import Prelude ( (.) )
import Data.Function ( ($) )
import Data.Either ( Either(Left, Right), either )
import Data.Maybe ( Maybe )
import Control.Monad ( (>>=), return, liftM )
import System.IO.Error ( IOError )
import System.IO ( IO )
#if __GLASGOW_HASKELL__ < 700
import Control.Monad ( fail )
#endif
import Control.Exception hiding
( throwIO, ioError, throwTo
, catch, catches, Handler(..), catchJust
, handle, handleJust
, try, tryJust
, evaluate
#if MIN_VERSION_base(4,3,0)
, mask, mask_
, uninterruptibleMask, uninterruptibleMask_
, getMaskingState
#if MIN_VERSION_base(4,4,0)
, allowInterrupt
#endif
#else
, block, unblock
#endif
#if !MIN_VERSION_base(4,4,0)
, blocked
#endif
, bracket, bracket_, bracketOnError
, finally, onException
)
import qualified Control.Exception as E
import qualified Control.Concurrent as C
import Control.Concurrent ( ThreadId )
#if !MIN_VERSION_base(4,4,0)
import Data.Bool ( Bool )
#endif
import Control.Monad.Base ( MonadBase, liftBase )
import Control.Monad.Trans.Control ( MonadBaseControl, StM
, liftBaseWith, restoreM
, control, liftBaseOp_
)
#if MIN_VERSION_base(4,3,0) || defined (__HADDOCK__)
import Control.Monad.Trans.Control ( liftBaseOp )
#endif
#include "inlinable.h"
throwIO :: (MonadBase IO m, Exception e) => e -> m a
throwIO = liftBase . E.throwIO
ioError :: MonadBase IO m => IOError -> m a
ioError = liftBase . E.ioError
throwTo :: (MonadBase IO m, Exception e) => ThreadId -> e -> m ()
throwTo tid e = liftBase $ C.throwTo tid e
catch :: (MonadBaseControl IO m, Exception e)
=> m a
-> (e -> m a)
-> m a
catch a handler = control $ \runInIO ->
E.catch (runInIO a)
(\e -> runInIO $ handler e)
catches :: MonadBaseControl IO m => m a -> [Handler m a] -> m a
catches a handlers = control $ \runInIO ->
E.catches (runInIO a)
[ E.Handler $ \e -> runInIO $ handler e
| Handler handler <- handlers
]
data Handler m a = forall e. Exception e => Handler (e -> m a)
catchJust :: (MonadBaseControl IO m, Exception e)
=> (e -> Maybe b)
-> m a
-> (b -> m a)
-> m a
catchJust p a handler = control $ \runInIO ->
E.catchJust p
(runInIO a)
(\e -> runInIO (handler e))
handle :: (MonadBaseControl IO m, Exception e) => (e -> m a) -> m a -> m a
handle handler a = control $ \runInIO ->
E.handle (\e -> runInIO (handler e))
(runInIO a)
handleJust :: (MonadBaseControl IO m, Exception e)
=> (e -> Maybe b) -> (b -> m a) -> m a -> m a
handleJust p handler a = control $ \runInIO ->
E.handleJust p (\e -> runInIO (handler e))
(runInIO a)
sequenceEither :: MonadBaseControl IO m => Either e (StM m a) -> m (Either e a)
sequenceEither = either (return . Left) (liftM Right . restoreM)
{-# INLINE sequenceEither #-}
try :: (MonadBaseControl IO m, Exception e) => m a -> m (Either e a)
try m = liftBaseWith (\runInIO -> E.try (runInIO m)) >>= sequenceEither
tryJust :: (MonadBaseControl IO m, Exception e) => (e -> Maybe b) -> m a -> m (Either b a)
tryJust p m = liftBaseWith (\runInIO -> E.tryJust p (runInIO m)) >>= sequenceEither
evaluate :: MonadBase IO m => a -> m a
evaluate = liftBase . E.evaluate
#if MIN_VERSION_base(4,3,0)
mask :: MonadBaseControl IO m => ((forall a. m a -> m a) -> m b) -> m b
mask = liftBaseOp E.mask . liftRestore
liftRestore :: MonadBaseControl IO m
=> ((forall a. m a -> m a) -> b)
-> ((forall a. IO a -> IO a) -> b)
liftRestore f r = f $ liftBaseOp_ r
{-# INLINE liftRestore #-}
mask_ :: MonadBaseControl IO m => m a -> m a
mask_ = liftBaseOp_ E.mask_
uninterruptibleMask :: MonadBaseControl IO m => ((forall a. m a -> m a) -> m b) -> m b
uninterruptibleMask = liftBaseOp E.uninterruptibleMask . liftRestore
uninterruptibleMask_ :: MonadBaseControl IO m => m a -> m a
uninterruptibleMask_ = liftBaseOp_ E.uninterruptibleMask_
getMaskingState :: MonadBase IO m => m MaskingState
getMaskingState = liftBase E.getMaskingState
#if MIN_VERSION_base(4,4,0)
allowInterrupt :: MonadBase IO m => m ()
allowInterrupt = liftBase E.allowInterrupt
#endif
#else
block :: MonadBaseControl IO m => m a -> m a
block = liftBaseOp_ E.block
unblock :: MonadBaseControl IO m => m a -> m a
unblock = liftBaseOp_ E.unblock
#endif
#if !MIN_VERSION_base(4,4,0)
blocked :: MonadBase IO m => m Bool
blocked = liftBase E.blocked
#endif
bracket :: MonadBaseControl IO m
=> m a
-> (a -> m b)
-> (a -> m c)
-> m c
bracket before after thing = control $ \runInIO ->
E.bracket (runInIO before)
(\st -> runInIO $ restoreM st >>= after)
(\st -> runInIO $ restoreM st >>= thing)
bracket_ :: MonadBaseControl IO m
=> m a
-> m b
-> m c
-> m c
bracket_ before after thing = control $ \runInIO ->
E.bracket_ (runInIO before)
(runInIO after)
(runInIO thing)
bracketOnError :: MonadBaseControl IO m
=> m a
-> (a -> m b)
-> (a -> m c)
-> m c
bracketOnError before after thing =
control $ \runInIO ->
E.bracketOnError (runInIO before)
(\st -> runInIO $ restoreM st >>= after)
(\st -> runInIO $ restoreM st >>= thing)
finally :: MonadBaseControl IO m
=> m a
-> m b
-> m a
finally a sequel = control $ \runInIO ->
E.finally (runInIO a)
(runInIO sequel)
onException :: MonadBaseControl IO m => m a -> m b -> m a
onException m what = control $ \runInIO ->
E.onException (runInIO m)
(runInIO what)