{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE UnicodeSyntax #-}
module Control.Monad.With where
import Control.Exception.Safe
import Control.Monad.Reader
import Control.Monad.ST
import Control.Monad.Trans.Resource.Internal
import Data.Functor.Identity
import Data.GeneralAllocate
import Data.Void
class Monad m ⇒ MonadWith m where
type WithException m
type WithException m = SomeException
stateThreadingGeneralWith
∷ GeneralAllocate m (WithException m) releaseReturn b a
→ (a → m b)
→ m (b, releaseReturn)
type With m = GeneralAllocate m (WithException m) ()
generalWith
∷ (MonadWith m)
⇒ With m b a
→ (a → m b)
→ m b
generalWith :: forall (m :: * -> *) b a.
MonadWith m =>
With m b a -> (a -> m b) -> m b
generalWith With m b a
alloc = (forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) releaseReturn b a.
MonadWith m =>
GeneralAllocate m (WithException m) releaseReturn b a
-> (a -> m b) -> m (b, releaseReturn)
stateThreadingGeneralWith With m b a
alloc
onFailure
∷ (MonadWith m)
⇒ m a
→ (WithException m → m b)
→ m a
onFailure :: forall (m :: * -> *) a b.
MonadWith m =>
m a -> (WithException m -> m b) -> m a
onFailure m a
go WithException m -> m b
err = forall (m :: * -> *) b a.
MonadWith m =>
With m b a -> (a -> m b) -> m b
generalWith GeneralAllocate m (WithException m) () a ()
alloc (forall a b. a -> b -> a
const m a
go)
where
alloc :: GeneralAllocate m (WithException m) () a ()
alloc = forall (m :: * -> *) e releaseReturn releaseArg a.
((forall x. m x -> m x)
-> m (GeneralAllocated m e releaseReturn releaseArg a))
-> GeneralAllocate m e releaseReturn releaseArg a
GeneralAllocate forall a b. (a -> b) -> a -> b
$ \forall x. m x -> m x
_ → forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) e releaseReturn releaseArg a.
a
-> (GeneralReleaseType e releaseArg -> m releaseReturn)
-> GeneralAllocated m e releaseReturn releaseArg a
GeneralAllocated () GeneralReleaseType (WithException m) a -> m ()
rel
rel :: GeneralReleaseType (WithException m) a -> m ()
rel (ReleaseFailure WithException m
e) = WithException m -> m b
err WithException m
e forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
rel GeneralReleaseType (WithException m) a
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
generalFinally
∷ (MonadWith m)
⇒ m a
→ m b
→ m (a, b)
generalFinally :: forall (m :: * -> *) a b. MonadWith m => m a -> m b -> m (a, b)
generalFinally m a
go m b
fin = forall (m :: * -> *) releaseReturn b a.
MonadWith m =>
GeneralAllocate m (WithException m) releaseReturn b a
-> (a -> m b) -> m (b, releaseReturn)
stateThreadingGeneralWith GeneralAllocate m (WithException m) b a ()
alloc forall a b. (a -> b) -> a -> b
$ forall a b. a -> b -> a
const m a
go
where
alloc :: GeneralAllocate m (WithException m) b a ()
alloc = forall (m :: * -> *) e releaseReturn releaseArg a.
((forall x. m x -> m x)
-> m (GeneralAllocated m e releaseReturn releaseArg a))
-> GeneralAllocate m e releaseReturn releaseArg a
GeneralAllocate forall a b. (a -> b) -> a -> b
$ \forall x. m x -> m x
_ → forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) e releaseReturn releaseArg a.
a
-> (GeneralReleaseType e releaseArg -> m releaseReturn)
-> GeneralAllocated m e releaseReturn releaseArg a
GeneralAllocated () GeneralReleaseType (WithException m) a -> m b
rel
rel :: GeneralReleaseType (WithException m) a -> m b
rel GeneralReleaseType (WithException m) a
_ = m b
fin
instance MonadWith IO where
stateThreadingGeneralWith :: forall releaseReturn b a.
GeneralAllocate IO (WithException IO) releaseReturn b a
-> (a -> IO b) -> IO (b, releaseReturn)
stateThreadingGeneralWith (GeneralAllocate (forall x. IO x -> IO x)
-> IO (GeneralAllocated IO (WithException IO) releaseReturn b a)
allocArg) a -> IO b
go = forall (m :: * -> *) b.
MonadMask m =>
((forall a. m a -> m a) -> m b) -> m b
mask forall a b. (a -> b) -> a -> b
$ \forall x. IO x -> IO x
restore → do
GeneralAllocated a
res GeneralReleaseType SomeException b -> IO releaseReturn
releaseRes ← (forall x. IO x -> IO x)
-> IO (GeneralAllocated IO (WithException IO) releaseReturn b a)
allocArg forall x. IO x -> IO x
restore
b
b ←
forall x. IO x -> IO x
restore (a -> IO b
go a
res) forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` \SomeException
e → do
releaseReturn
_ ← GeneralReleaseType SomeException b -> IO releaseReturn
releaseRes forall a b. (a -> b) -> a -> b
$ forall e a. e -> GeneralReleaseType e a
ReleaseFailure SomeException
e
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM SomeException
e
releaseReturn
c ← GeneralReleaseType SomeException b -> IO releaseReturn
releaseRes forall a b. (a -> b) -> a -> b
$ forall e a. a -> GeneralReleaseType e a
ReleaseSuccess b
b
forall (f :: * -> *) a. Applicative f => a -> f a
pure (b
b, releaseReturn
c)
newtype WithNoContinuation m a = WithNoContinuation (m a) deriving newtype (forall a b. a -> WithNoContinuation m b -> WithNoContinuation m a
forall a b.
(a -> b) -> WithNoContinuation m a -> WithNoContinuation m b
forall (m :: * -> *) a b.
Functor m =>
a -> WithNoContinuation m b -> WithNoContinuation m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> WithNoContinuation m a -> WithNoContinuation m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> WithNoContinuation m b -> WithNoContinuation m a
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> WithNoContinuation m b -> WithNoContinuation m a
fmap :: forall a b.
(a -> b) -> WithNoContinuation m a -> WithNoContinuation m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> WithNoContinuation m a -> WithNoContinuation m b
Functor, forall a. a -> WithNoContinuation m a
forall a b.
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m a
forall a b.
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m b
forall a b.
WithNoContinuation m (a -> b)
-> WithNoContinuation m a -> WithNoContinuation m b
forall a b c.
(a -> b -> c)
-> WithNoContinuation m a
-> WithNoContinuation m b
-> WithNoContinuation m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
forall {m :: * -> *}.
Applicative m =>
Functor (WithNoContinuation m)
forall (m :: * -> *) a.
Applicative m =>
a -> WithNoContinuation m a
forall (m :: * -> *) a b.
Applicative m =>
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m a
forall (m :: * -> *) a b.
Applicative m =>
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m b
forall (m :: * -> *) a b.
Applicative m =>
WithNoContinuation m (a -> b)
-> WithNoContinuation m a -> WithNoContinuation m b
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> WithNoContinuation m a
-> WithNoContinuation m b
-> WithNoContinuation m c
<* :: forall a b.
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m a
$c<* :: forall (m :: * -> *) a b.
Applicative m =>
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m a
*> :: forall a b.
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m b
$c*> :: forall (m :: * -> *) a b.
Applicative m =>
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m b
liftA2 :: forall a b c.
(a -> b -> c)
-> WithNoContinuation m a
-> WithNoContinuation m b
-> WithNoContinuation m c
$cliftA2 :: forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> WithNoContinuation m a
-> WithNoContinuation m b
-> WithNoContinuation m c
<*> :: forall a b.
WithNoContinuation m (a -> b)
-> WithNoContinuation m a -> WithNoContinuation m b
$c<*> :: forall (m :: * -> *) a b.
Applicative m =>
WithNoContinuation m (a -> b)
-> WithNoContinuation m a -> WithNoContinuation m b
pure :: forall a. a -> WithNoContinuation m a
$cpure :: forall (m :: * -> *) a.
Applicative m =>
a -> WithNoContinuation m a
Applicative, forall a. a -> WithNoContinuation m a
forall a b.
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m b
forall a b.
WithNoContinuation m a
-> (a -> WithNoContinuation m b) -> WithNoContinuation m b
forall {m :: * -> *}. Monad m => Applicative (WithNoContinuation m)
forall (m :: * -> *) a. Monad m => a -> WithNoContinuation m a
forall (m :: * -> *) a b.
Monad m =>
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m b
forall (m :: * -> *) a b.
Monad m =>
WithNoContinuation m a
-> (a -> WithNoContinuation m b) -> WithNoContinuation m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> WithNoContinuation m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> WithNoContinuation m a
>> :: forall a b.
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
WithNoContinuation m a
-> WithNoContinuation m b -> WithNoContinuation m b
>>= :: forall a b.
WithNoContinuation m a
-> (a -> WithNoContinuation m b) -> WithNoContinuation m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
WithNoContinuation m a
-> (a -> WithNoContinuation m b) -> WithNoContinuation m b
Monad)
instance (Monad m) ⇒ MonadWith (WithNoContinuation m) where
type WithException (WithNoContinuation m) = Void
stateThreadingGeneralWith :: forall releaseReturn b a.
GeneralAllocate
(WithNoContinuation m)
(WithException (WithNoContinuation m))
releaseReturn
b
a
-> (a -> WithNoContinuation m b)
-> WithNoContinuation m (b, releaseReturn)
stateThreadingGeneralWith (GeneralAllocate (forall x. WithNoContinuation m x -> WithNoContinuation m x)
-> WithNoContinuation
m
(GeneralAllocated
(WithNoContinuation m)
(WithException (WithNoContinuation m))
releaseReturn
b
a)
allocArg) a -> WithNoContinuation m b
go = forall (m :: * -> *) a. m a -> WithNoContinuation m a
WithNoContinuation forall a b. (a -> b) -> a -> b
$ do
let WithNoContinuation m (GeneralAllocated
(WithNoContinuation m)
(WithException (WithNoContinuation m))
releaseReturn
b
a)
allocArg' = (forall x. WithNoContinuation m x -> WithNoContinuation m x)
-> WithNoContinuation
m
(GeneralAllocated
(WithNoContinuation m)
(WithException (WithNoContinuation m))
releaseReturn
b
a)
allocArg forall a. a -> a
id
GeneralAllocated a
res GeneralReleaseType Void b -> WithNoContinuation m releaseReturn
releaseRes ← m (GeneralAllocated
(WithNoContinuation m)
(WithException (WithNoContinuation m))
releaseReturn
b
a)
allocArg'
let WithNoContinuation m b
go' = a -> WithNoContinuation m b
go a
res
b
b ← m b
go'
let WithNoContinuation m releaseReturn
releaseRes' = GeneralReleaseType Void b -> WithNoContinuation m releaseReturn
releaseRes forall a b. (a -> b) -> a -> b
$ forall e a. a -> GeneralReleaseType e a
ReleaseSuccess b
b
releaseReturn
c ← m releaseReturn
releaseRes'
forall (f :: * -> *) a. Applicative f => a -> f a
pure (b
b, releaseReturn
c)
deriving via WithNoContinuation (ST s) instance MonadWith (ST s)
deriving via WithNoContinuation Identity instance MonadWith Identity
instance (MonadWith m) ⇒ MonadWith (ReaderT r m) where
type WithException (ReaderT r m) = WithException m
stateThreadingGeneralWith
∷ ∀ a b releaseReturn
. GeneralAllocate (ReaderT r m) (WithException m) releaseReturn b a
→ (a → ReaderT r m b)
→ ReaderT r m (b, releaseReturn)
stateThreadingGeneralWith :: forall a b releaseReturn.
GeneralAllocate (ReaderT r m) (WithException m) releaseReturn b a
-> (a -> ReaderT r m b) -> ReaderT r m (b, releaseReturn)
stateThreadingGeneralWith (GeneralAllocate (forall x. ReaderT r m x -> ReaderT r m x)
-> ReaderT
r
m
(GeneralAllocated
(ReaderT r m) (WithException m) releaseReturn b a)
allocFun) a -> ReaderT r m b
go = forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT forall a b. (a -> b) -> a -> b
$ \r
r → do
let
allocFun' ∷ (∀ x. m x → m x) → m (GeneralAllocated m (WithException m) releaseReturn b a)
allocFun' :: (forall x. m x -> m x)
-> m (GeneralAllocated m (WithException m) releaseReturn b a)
allocFun' forall x. m x -> m x
restore = do
let
restore' ∷ ∀ x. ReaderT r m x → ReaderT r m x
restore' :: forall x. ReaderT r m x -> ReaderT r m x
restore' ReaderT r m x
mx = forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT forall a b. (a -> b) -> a -> b
$ forall x. m x -> m x
restore forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT r m x
mx
GeneralAllocated a
x GeneralReleaseType (WithException m) b -> ReaderT r m releaseReturn
release ← forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ((forall x. ReaderT r m x -> ReaderT r m x)
-> ReaderT
r
m
(GeneralAllocated
(ReaderT r m) (WithException m) releaseReturn b a)
allocFun forall x. ReaderT r m x -> ReaderT r m x
restore') r
r
let
release' :: GeneralReleaseType (WithException m) b -> m releaseReturn
release' GeneralReleaseType (WithException m) b
relTy = forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (GeneralReleaseType (WithException m) b -> ReaderT r m releaseReturn
release GeneralReleaseType (WithException m) b
relTy) r
r
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) e releaseReturn releaseArg a.
a
-> (GeneralReleaseType e releaseArg -> m releaseReturn)
-> GeneralAllocated m e releaseReturn releaseArg a
GeneralAllocated a
x GeneralReleaseType (WithException m) b -> m releaseReturn
release'
forall (m :: * -> *) releaseReturn b a.
MonadWith m =>
GeneralAllocate m (WithException m) releaseReturn b a
-> (a -> m b) -> m (b, releaseReturn)
stateThreadingGeneralWith (forall (m :: * -> *) e releaseReturn releaseArg a.
((forall x. m x -> m x)
-> m (GeneralAllocated m e releaseReturn releaseArg a))
-> GeneralAllocate m e releaseReturn releaseArg a
GeneralAllocate (forall x. m x -> m x)
-> m (GeneralAllocated m (WithException m) releaseReturn b a)
allocFun') (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT r
r forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ReaderT r m b
go)
instance (MonadWith m) ⇒ MonadWith (ResourceT m) where
type WithException (ResourceT m) = WithException m
stateThreadingGeneralWith
∷ ∀ a b releaseReturn
. GeneralAllocate (ResourceT m) (WithException m) releaseReturn b a
→ (a → ResourceT m b)
→ ResourceT m (b, releaseReturn)
stateThreadingGeneralWith :: forall a b releaseReturn.
GeneralAllocate (ResourceT m) (WithException m) releaseReturn b a
-> (a -> ResourceT m b) -> ResourceT m (b, releaseReturn)
stateThreadingGeneralWith (GeneralAllocate (forall x. ResourceT m x -> ResourceT m x)
-> ResourceT
m
(GeneralAllocated
(ResourceT m) (WithException m) releaseReturn b a)
allocFun) a -> ResourceT m b
go = forall (m :: * -> *) a. (IORef ReleaseMap -> m a) -> ResourceT m a
ResourceT forall a b. (a -> b) -> a -> b
$ \IORef ReleaseMap
st → do
let
allocFun' ∷ (∀ x. m x → m x) → m (GeneralAllocated m (WithException m) releaseReturn b a)
allocFun' :: (forall x. m x -> m x)
-> m (GeneralAllocated m (WithException m) releaseReturn b a)
allocFun' forall x. m x -> m x
restore = do
let
restore' ∷ ∀ x. ResourceT m x → ResourceT m x
restore' :: forall x. ResourceT m x -> ResourceT m x
restore' ResourceT m x
mx = forall (m :: * -> *) a. (IORef ReleaseMap -> m a) -> ResourceT m a
ResourceT forall a b. (a -> b) -> a -> b
$ forall x. m x -> m x
restore forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. ResourceT m a -> IORef ReleaseMap -> m a
unResourceT ResourceT m x
mx
GeneralAllocated a
x GeneralReleaseType (WithException m) b -> ResourceT m releaseReturn
release ← forall (m :: * -> *) a. ResourceT m a -> IORef ReleaseMap -> m a
unResourceT ((forall x. ResourceT m x -> ResourceT m x)
-> ResourceT
m
(GeneralAllocated
(ResourceT m) (WithException m) releaseReturn b a)
allocFun forall x. ResourceT m x -> ResourceT m x
restore') IORef ReleaseMap
st
let
release' :: GeneralReleaseType (WithException m) b -> m releaseReturn
release' GeneralReleaseType (WithException m) b
relTy = forall (m :: * -> *) a. ResourceT m a -> IORef ReleaseMap -> m a
unResourceT (GeneralReleaseType (WithException m) b -> ResourceT m releaseReturn
release GeneralReleaseType (WithException m) b
relTy) IORef ReleaseMap
st
forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) e releaseReturn releaseArg a.
a
-> (GeneralReleaseType e releaseArg -> m releaseReturn)
-> GeneralAllocated m e releaseReturn releaseArg a
GeneralAllocated a
x GeneralReleaseType (WithException m) b -> m releaseReturn
release'
forall (m :: * -> *) releaseReturn b a.
MonadWith m =>
GeneralAllocate m (WithException m) releaseReturn b a
-> (a -> m b) -> m (b, releaseReturn)
stateThreadingGeneralWith (forall (m :: * -> *) e releaseReturn releaseArg a.
((forall x. m x -> m x)
-> m (GeneralAllocated m e releaseReturn releaseArg a))
-> GeneralAllocate m e releaseReturn releaseArg a
GeneralAllocate (forall x. m x -> m x)
-> m (GeneralAllocated m (WithException m) releaseReturn b a)
allocFun') (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (m :: * -> *) a. ResourceT m a -> IORef ReleaseMap -> m a
unResourceT IORef ReleaseMap
st forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ResourceT m b
go)