{-# LANGUAGE CPP #-}
{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ImpredicativeTypes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Control.Monad.Exception
(
MonadThrow
, exception
, throw
, throwIO
, ioError
, throwTo
, MonadCatch
, catch
, handle
, catchJust
, handleJust
, Handler(..)
, catches
, handles
, try
, tryJust
, evaluateIO
, MonadMask(..)
, liftGetMaskingState
, liftWithMaskingState
, mask
, mask_
, uninterruptibleMask
, uninterruptibleMask_
, interruptible
, allowInterrupt
, module Control.Monad.Abort.Class
, module Control.Monad.Finally
, module Control.Exception
) where
#if !MIN_VERSION_base(4,6,0)
import Prelude hiding (catch)
#else
import Prelude hiding (ioError)
#endif
import Data.Monoid (Monoid)
import Control.Applicative (Applicative, (<$>))
import Control.Monad (join, liftM)
import Control.Monad.Base
import Control.Monad.Trans.Class
import Control.Monad.Trans.Control (MonadTransControl(..))
import Control.Monad.Trans.Abort hiding (abort, recover)
import Control.Monad.Trans.Finish
import Control.Monad.Trans.Maybe
#if !MIN_VERSION_transformers(0,6,0)
import Control.Monad.Trans.List
import Control.Monad.Trans.Error
#endif
import Control.Monad.Trans.Except
import Control.Monad.Trans.Reader
import qualified Control.Monad.Trans.State.Lazy as L
import qualified Control.Monad.Trans.State.Strict as S
import qualified Control.Monad.Trans.Writer.Lazy as L
import qualified Control.Monad.Trans.Writer.Strict as S
import qualified Control.Monad.Trans.RWS.Lazy as L
import qualified Control.Monad.Trans.RWS.Strict as S
import Control.Monad.Abort.Class
import Control.Monad.Finally
import Control.Concurrent (ThreadId)
import Control.Exception hiding (
evaluate, throw, throwIO, ioError, throwTo, catch, catchJust, handle,
handleJust, Handler(..), catches, try, tryJust, finally, onException,
#if !MIN_VERSION_base(4,7,0)
block, unblock, blocked,
#endif
getMaskingState, mask, mask_, uninterruptibleMask, uninterruptibleMask_,
#if MIN_VERSION_base(4,9,0)
interruptible,
#endif
allowInterrupt, bracket, bracket_, bracketOnError)
import qualified Control.Exception as E
import GHC.Base (maskAsyncExceptions#, maskUninterruptible#,
unmaskAsyncExceptions#)
import GHC.IO (IO(..))
type MonadThrow μ = MonadAbort SomeException μ
exception ∷ Exception e ⇒ e → α
exception :: forall e α. Exception e => e -> α
exception = forall a e. Exception e => e -> a
E.throw
{-# INLINE exception #-}
throw ∷ (MonadThrow μ, Exception e) ⇒ e → μ α
throw :: forall (μ :: * -> *) e α. (MonadThrow μ, Exception e) => e -> μ α
throw = forall e (μ :: * -> *) α. MonadAbort e μ => e -> μ α
abort forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e. Exception e => e -> SomeException
toException
{-# INLINE throw #-}
throwIO ∷ (MonadBase IO μ, Exception e) ⇒ e → μ α
throwIO :: forall (μ :: * -> *) e α. (MonadBase IO μ, Exception e) => e -> μ α
throwIO = forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e a. Exception e => e -> IO a
E.throwIO
{-# INLINE throwIO #-}
ioError ∷ MonadBase IO μ ⇒ IOError → μ α
ioError :: forall (μ :: * -> *) α. MonadBase IO μ => IOError -> μ α
ioError = forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IOError -> IO a
E.ioError
{-# INLINE ioError #-}
throwTo ∷ (MonadBase IO μ, Exception e) ⇒ ThreadId → e → μ ()
throwTo :: forall (μ :: * -> *) e.
(MonadBase IO μ, Exception e) =>
ThreadId -> e -> μ ()
throwTo = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e. Exception e => ThreadId -> e -> IO ()
E.throwTo
{-# INLINE throwTo #-}
type MonadCatch μ = MonadRecover SomeException μ
catch ∷ (MonadCatch μ, Exception e) ⇒ μ α → (e → μ α) → μ α
catch :: forall (μ :: * -> *) e α.
(MonadCatch μ, Exception e) =>
μ α -> (e -> μ α) -> μ α
catch μ α
m e -> μ α
h = forall e (μ :: * -> *) α.
MonadRecover e μ =>
μ α -> (e -> μ α) -> μ α
recover μ α
m forall a b. (a -> b) -> a -> b
$ \SomeException
e → forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (μ :: * -> *) e α. (MonadThrow μ, Exception e) => e -> μ α
throw SomeException
e) e -> μ α
h (forall e. Exception e => SomeException -> Maybe e
fromException SomeException
e)
{-# INLINE catch #-}
handle ∷ (MonadCatch μ, Exception e) ⇒ (e → μ α) → μ α → μ α
handle :: forall (μ :: * -> *) e α.
(MonadCatch μ, Exception e) =>
(e -> μ α) -> μ α -> μ α
handle = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (μ :: * -> *) e α.
(MonadCatch μ, Exception e) =>
μ α -> (e -> μ α) -> μ α
catch
{-# INLINE handle #-}
catchJust ∷ (MonadCatch μ, Exception e)
⇒ (e → Maybe β)
→ μ α
→ (β → μ α)
→ μ α
catchJust :: forall (μ :: * -> *) e β α.
(MonadCatch μ, Exception e) =>
(e -> Maybe β) -> μ α -> (β -> μ α) -> μ α
catchJust e -> Maybe β
f μ α
m β -> μ α
h = forall (μ :: * -> *) e α.
(MonadCatch μ, Exception e) =>
μ α -> (e -> μ α) -> μ α
catch μ α
m forall a b. (a -> b) -> a -> b
$ \e
e → forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (μ :: * -> *) e α. (MonadThrow μ, Exception e) => e -> μ α
throw e
e) β -> μ α
h forall a b. (a -> b) -> a -> b
$ e -> Maybe β
f e
e
{-# INLINE catchJust #-}
handleJust ∷ (MonadCatch μ, Exception e)
⇒ (e → Maybe β) → (β → μ α) → μ α → μ α
handleJust :: forall (μ :: * -> *) e β α.
(MonadCatch μ, Exception e) =>
(e -> Maybe β) -> (β -> μ α) -> μ α -> μ α
handleJust = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (μ :: * -> *) e β α.
(MonadCatch μ, Exception e) =>
(e -> Maybe β) -> μ α -> (β -> μ α) -> μ α
catchJust
{-# INLINE handleJust #-}
data Handler μ α = ∀ e . Exception e ⇒ Handler (e → μ α)
instance Functor μ ⇒ Functor (Handler μ) where
fmap :: forall a b. (a -> b) -> Handler μ a -> Handler μ b
fmap a -> b
f (Handler e -> μ a
h) = forall {k} (μ :: k -> *) (α :: k) e.
Exception e =>
(e -> μ α) -> Handler μ α
Handler (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> μ a
h)
{-# INLINE fmap #-}
catches ∷ MonadCatch μ ⇒ μ α → [Handler μ α] → μ α
catches :: forall (μ :: * -> *) α. MonadCatch μ => μ α -> [Handler μ α] -> μ α
catches μ α
m = forall e (μ :: * -> *) α.
MonadRecover e μ =>
μ α -> (e -> μ α) -> μ α
recover μ α
m forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {μ :: * -> *} {α}.
MonadAbort SomeException μ =>
[Handler μ α] -> SomeException -> μ α
hl
where hl :: [Handler μ α] -> SomeException -> μ α
hl [] SomeException
e = forall e (μ :: * -> *) α. MonadAbort e μ => e -> μ α
abort SomeException
e
hl (Handler e -> μ α
h : [Handler μ α]
hs) SomeException
e = forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([Handler μ α] -> SomeException -> μ α
hl [Handler μ α]
hs SomeException
e) e -> μ α
h forall a b. (a -> b) -> a -> b
$ forall e. Exception e => SomeException -> Maybe e
fromException SomeException
e
handles ∷ MonadCatch μ ⇒ [Handler μ α] → μ α → μ α
handles :: forall (μ :: * -> *) α. MonadCatch μ => [Handler μ α] -> μ α -> μ α
handles = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (μ :: * -> *) α. MonadCatch μ => μ α -> [Handler μ α] -> μ α
catches
{-# INLINE handles #-}
try ∷ (MonadCatch μ, Exception e) ⇒ μ α → μ (Either e α)
try :: forall (μ :: * -> *) e α.
(MonadCatch μ, Exception e) =>
μ α -> μ (Either e α)
try μ α
m = forall (μ :: * -> *) e α.
(MonadCatch μ, Exception e) =>
μ α -> (e -> μ α) -> μ α
catch (forall a b. b -> Either a b
Right forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> μ α
m) (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left)
{-# INLINE try #-}
tryJust ∷ (MonadCatch μ, Exception e)
⇒ (e → Maybe β)
→ μ α
→ μ (Either β α)
tryJust :: forall (μ :: * -> *) e β α.
(MonadCatch μ, Exception e) =>
(e -> Maybe β) -> μ α -> μ (Either β α)
tryJust e -> Maybe β
h μ α
m = forall (μ :: * -> *) e α.
(MonadCatch μ, Exception e) =>
μ α -> (e -> μ α) -> μ α
catch (forall a b. b -> Either a b
Right forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> μ α
m) forall a b. (a -> b) -> a -> b
$ \e
e →
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (μ :: * -> *) e α. (MonadThrow μ, Exception e) => e -> μ α
throw e
e) (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left) (e -> Maybe β
h e
e)
{-# INLINE tryJust #-}
evaluateIO ∷ MonadBase IO μ ⇒ α → μ α
evaluateIO :: forall (μ :: * -> *) α. MonadBase IO μ => α -> μ α
evaluateIO = forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> IO a
E.evaluate
{-# INLINE evaluateIO #-}
class (Applicative μ, Monad μ) ⇒ MonadMask μ where
getMaskingState ∷ μ MaskingState
default getMaskingState ∷ (MonadMask η, MonadTrans t, μ ~ t η)
⇒ μ MaskingState
getMaskingState = forall (μ :: * -> *) (t :: (* -> *) -> * -> *).
(MonadMask μ, MonadTrans t) =>
t μ MaskingState
liftGetMaskingState
{-# INLINE getMaskingState #-}
withMaskingState ∷ MaskingState → μ α → μ α
default withMaskingState ∷ (MonadMask η, MonadTransControl t, μ ~ t η)
⇒ MaskingState → μ α → μ α
withMaskingState = forall (t :: (* -> *) -> * -> *) (μ :: * -> *) α.
(MonadTransControl t, MonadMask μ, Monad (t μ)) =>
MaskingState -> t μ α -> t μ α
liftWithMaskingState
{-# INLINE withMaskingState #-}
liftGetMaskingState ∷ (MonadMask μ, MonadTrans t) ⇒ t μ MaskingState
liftGetMaskingState :: forall (μ :: * -> *) (t :: (* -> *) -> * -> *).
(MonadMask μ, MonadTrans t) =>
t μ MaskingState
liftGetMaskingState = forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall (μ :: * -> *). MonadMask μ => μ MaskingState
getMaskingState
{-# INLINE liftGetMaskingState #-}
liftWithMaskingState ∷ (MonadTransControl t, MonadMask μ, Monad (t μ))
⇒ MaskingState → t μ α → t μ α
liftWithMaskingState :: forall (t :: (* -> *) -> * -> *) (μ :: * -> *) α.
(MonadTransControl t, MonadMask μ, Monad (t μ)) =>
MaskingState -> t μ α -> t μ α
liftWithMaskingState MaskingState
ms t μ α
m =
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTransControl t, Monad m) =>
m (StT t a) -> t m a
restoreT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => a -> m a
return) forall a b. (a -> b) -> a -> b
$ forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTransControl t, Monad m) =>
(Run t -> m a) -> t m a
liftWith forall a b. (a -> b) -> a -> b
$ \Run t
run →
forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
ms (Run t
run t μ α
m)
{-# INLINE liftWithMaskingState #-}
instance MonadMask IO where
getMaskingState :: IO MaskingState
getMaskingState = IO MaskingState
E.getMaskingState
withMaskingState :: forall α. MaskingState -> IO α -> IO α
withMaskingState MaskingState
Unmasked (IO State# RealWorld -> (# State# RealWorld, α #)
io) = forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO forall a b. (a -> b) -> a -> b
$ forall a.
(State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld -> (# State# RealWorld, a #)
unmaskAsyncExceptions# State# RealWorld -> (# State# RealWorld, α #)
io
withMaskingState MaskingState
MaskedInterruptible (IO State# RealWorld -> (# State# RealWorld, α #)
io) = forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO forall a b. (a -> b) -> a -> b
$ forall a.
(State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld -> (# State# RealWorld, a #)
maskAsyncExceptions# State# RealWorld -> (# State# RealWorld, α #)
io
withMaskingState MaskingState
MaskedUninterruptible (IO State# RealWorld -> (# State# RealWorld, α #)
io) = forall a. (State# RealWorld -> (# State# RealWorld, a #)) -> IO a
IO forall a b. (a -> b) -> a -> b
$ forall a.
(State# RealWorld -> (# State# RealWorld, a #))
-> State# RealWorld -> (# State# RealWorld, a #)
maskUninterruptible# State# RealWorld -> (# State# RealWorld, α #)
io
instance MonadMask μ ⇒ MonadMask (MaybeT μ)
#if !MIN_VERSION_transformers(0,6,0)
instance MonadMask μ ⇒ MonadMask (ListT μ)
#endif
instance MonadMask μ ⇒ MonadMask (AbortT e μ)
instance MonadMask μ ⇒ MonadMask (FinishT β μ)
#if !MIN_VERSION_transformers(0,6,0)
instance (MonadMask μ, Error e) ⇒ MonadMask (ErrorT e μ)
#endif
instance MonadMask μ ⇒ MonadMask (ExceptT e μ)
instance MonadMask μ ⇒ MonadMask (ReaderT r μ)
instance MonadMask μ ⇒ MonadMask (L.StateT s μ)
instance MonadMask μ ⇒ MonadMask (S.StateT s μ)
instance (MonadMask μ, Monoid w) ⇒ MonadMask (L.WriterT w μ)
instance (MonadMask μ, Monoid w) ⇒ MonadMask (S.WriterT w μ)
instance (MonadMask μ, Monoid w) ⇒ MonadMask (L.RWST r w s μ)
instance (MonadMask μ, Monoid w) ⇒ MonadMask (S.RWST r w s μ)
mask ∷ ∀ μ α . MonadMask μ
⇒ ((∀ η β . MonadMask η ⇒ η β → η β) → μ α) → μ α
mask :: forall (μ :: * -> *) α.
MonadMask μ =>
((forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α) -> μ α
mask (forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α
f = forall (μ :: * -> *). MonadMask μ => μ MaskingState
getMaskingState forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
MaskingState
Unmasked →
forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
MaskedInterruptible forall a b. (a -> b) -> a -> b
$ (forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α
f (forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
Unmasked)
MaskingState
MaskedInterruptible →
(forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α
f (forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
MaskedInterruptible)
MaskingState
MaskedUninterruptible →
(forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α
f (forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
MaskedUninterruptible)
mask_ ∷ ∀ μ α . MonadMask μ ⇒ μ α → μ α
mask_ :: forall (η :: * -> *) β. MonadMask η => η β -> η β
mask_ = forall (μ :: * -> *) α.
MonadMask μ =>
((forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α) -> μ α
mask forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> b -> a
const
{-# INLINE mask_ #-}
uninterruptibleMask ∷ MonadMask μ
⇒ ((∀ η β . MonadMask η ⇒ η β → η β) → μ α) → μ α
uninterruptibleMask :: forall (μ :: * -> *) α.
MonadMask μ =>
((forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α) -> μ α
uninterruptibleMask (forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α
f = forall (μ :: * -> *). MonadMask μ => μ MaskingState
getMaskingState forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
MaskingState
Unmasked →
forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
MaskedUninterruptible forall a b. (a -> b) -> a -> b
$ (forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α
f (forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
Unmasked)
MaskingState
MaskedInterruptible →
forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
MaskedUninterruptible forall a b. (a -> b) -> a -> b
$
(forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α
f (forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
MaskedInterruptible)
MaskingState
MaskedUninterruptible →
(forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α
f (forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
MaskedUninterruptible)
uninterruptibleMask_ ∷ MonadMask μ ⇒ μ α → μ α
uninterruptibleMask_ :: forall (η :: * -> *) β. MonadMask η => η β -> η β
uninterruptibleMask_ = forall (μ :: * -> *) α.
MonadMask μ =>
((forall (η :: * -> *) β. MonadMask η => η β -> η β) -> μ α) -> μ α
uninterruptibleMask forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> b -> a
const
{-# INLINE uninterruptibleMask_ #-}
interruptible ∷ MonadMask μ ⇒ μ α → μ α
interruptible :: forall (η :: * -> *) β. MonadMask η => η β -> η β
interruptible μ α
m = forall (μ :: * -> *). MonadMask μ => μ MaskingState
getMaskingState forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
MaskingState
Unmasked → μ α
m
MaskingState
MaskedInterruptible → forall (μ :: * -> *) α. MonadMask μ => MaskingState -> μ α -> μ α
withMaskingState MaskingState
Unmasked μ α
m
MaskingState
MaskedUninterruptible → μ α
m
allowInterrupt ∷ MonadMask μ ⇒ μ ()
allowInterrupt :: forall (μ :: * -> *). MonadMask μ => μ ()
allowInterrupt = forall (η :: * -> *) β. MonadMask η => η β -> η β
interruptible forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return ()
{-# INLINE allowInterrupt #-}