module Control.Effect.Bracket
(
Bracket(..)
, ExitCase(..)
, generalBracket
, bracket
, bracket_
, bracketOnError
, onError
, finally
, bracketToIO
, runBracketLocally
, ignoreBracket
, threadBracketViaClass
, C.MonadMask
, BracketToIOC
, BracketLocallyC
, IgnoreBracketC
) where
import Control.Effect
import Control.Effect.Primitive
import Control.Effect.Type.Bracket
import Control.Monad
import Control.Monad.Catch (MonadMask)
import qualified Control.Monad.Catch as C
generalBracket :: Eff Bracket m
=> m a
-> (a -> ExitCase b -> m c)
-> (a -> m b)
-> m (b, c)
generalBracket acquire release use = send (GeneralBracket acquire release use)
{-# INLINE generalBracket #-}
bracket :: Eff Bracket m
=> m a
-> (a -> m c)
-> (a -> m b)
-> m b
bracket acquire release use = do
(b, _) <- generalBracket acquire (\a _ -> release a) use
return b
{-# INLINE bracket #-}
bracket_ :: Eff Bracket m
=> m a
-> m c
-> m b
-> m b
bracket_ acquire release use = bracket acquire (const release) (const use)
{-# INLINE bracket_ #-}
bracketOnError :: Eff Bracket m
=> m a
-> (a -> m c)
-> (a -> m b)
-> m b
bracketOnError acquire release use = do
(b, _) <- generalBracket
acquire
(\a -> \case
ExitCaseSuccess _ -> pure ()
_ -> void $ release a
)
use
return b
{-# INLINE bracketOnError #-}
onError :: Eff Bracket m => m a -> m b -> m a
onError m h = bracketOnError (pure ()) (const h) (const m)
{-# INLINE onError #-}
finally :: Eff Bracket m => m a -> m b -> m a
finally m h = bracket (pure ()) (const h) (const m)
{-# INLINE finally #-}
data BracketToIOH
instance (Carrier m, MonadMask m)
=> PrimHandler BracketToIOH Bracket m where
effPrimHandler (GeneralBracket acquire release use) =
C.generalBracket acquire release use
{-# INLINEABLE effPrimHandler #-}
type BracketToIOC = InterpretPrimC BracketToIOH Bracket
bracketToIO :: (Carrier m, MonadMask m)
=> BracketToIOC m a
-> m a
bracketToIO = interpretPrimViaHandler
{-# INLINE bracketToIO #-}
data BracketLocallyH
instance Carrier m => PrimHandler BracketLocallyH Bracket m where
effPrimHandler (GeneralBracket acquire release use) = do
a <- acquire
b <- use a
c <- release a (ExitCaseSuccess b)
return (b, c)
{-# INLINEABLE effPrimHandler #-}
type BracketLocallyC = InterpretPrimC BracketLocallyH Bracket
runBracketLocally :: Carrier m
=> BracketLocallyC m a
-> m a
runBracketLocally = interpretPrimViaHandler
{-# INLINE runBracketLocally #-}
type IgnoreBracketC = InterpretC IgnoreBracketH Bracket
data IgnoreBracketH
instance Carrier m => Handler IgnoreBracketH Bracket m where
effHandler (GeneralBracket acquire release use) = do
a <- acquire
b <- use a
c <- release a (ExitCaseSuccess b)
return (b, c)
{-# INLINEABLE effHandler #-}
ignoreBracket :: Carrier m
=> IgnoreBracketC m a
-> m a
ignoreBracket = interpretViaHandler
{-# INLINE ignoreBracket #-}