{-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, MultiParamTypeClasses, RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeOperators, UndecidableInstances #-}
module Control.Effect.Resource
( -- * Resource effect
  Resource(..)
, bracket
, bracketOnError
, finally
, onException
  -- * Resource carrier
, runResource
, ResourceC(..)
) where

import           Control.Applicative (Alternative(..))
import           Control.Effect.Carrier
import           Control.Effect.Reader
import qualified Control.Exception as Exc
import           Control.Monad (MonadPlus(..))
import qualified Control.Monad.Fail as Fail
import           Control.Monad.Fix
import           Control.Monad.IO.Class
import           Control.Monad.IO.Unlift
import           Control.Monad.Trans.Class

data Resource m k
  = forall resource any output . Resource (m resource) (resource -> m any) (resource -> m output) (output -> m k)
  | forall resource any output . OnError  (m resource) (resource -> m any) (resource -> m output) (output -> m k)

deriving instance Functor m => Functor (Resource m)

instance HFunctor Resource where
  hmap :: (forall x. m x -> n x) -> Resource m a -> Resource n a
hmap f :: forall x. m x -> n x
f (Resource acquire :: m resource
acquire release :: resource -> m any
release use :: resource -> m output
use k :: output -> m a
k) = n resource
-> (resource -> n any)
-> (resource -> n output)
-> (output -> n a)
-> Resource n a
forall (m :: * -> *) k resource any output.
m resource
-> (resource -> m any)
-> (resource -> m output)
-> (output -> m k)
-> Resource m k
Resource (m resource -> n resource
forall x. m x -> n x
f m resource
acquire) (m any -> n any
forall x. m x -> n x
f (m any -> n any) -> (resource -> m any) -> resource -> n any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. resource -> m any
release) (m output -> n output
forall x. m x -> n x
f (m output -> n output)
-> (resource -> m output) -> resource -> n output
forall b c a. (b -> c) -> (a -> b) -> a -> c
. resource -> m output
use) (m a -> n a
forall x. m x -> n x
f (m a -> n a) -> (output -> m a) -> output -> n a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. output -> m a
k)
  hmap f :: forall x. m x -> n x
f (OnError acquire :: m resource
acquire release :: resource -> m any
release use :: resource -> m output
use k :: output -> m a
k)  = n resource
-> (resource -> n any)
-> (resource -> n output)
-> (output -> n a)
-> Resource n a
forall (m :: * -> *) k resource any output.
m resource
-> (resource -> m any)
-> (resource -> m output)
-> (output -> m k)
-> Resource m k
OnError  (m resource -> n resource
forall x. m x -> n x
f m resource
acquire) (m any -> n any
forall x. m x -> n x
f (m any -> n any) -> (resource -> m any) -> resource -> n any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. resource -> m any
release) (m output -> n output
forall x. m x -> n x
f (m output -> n output)
-> (resource -> m output) -> resource -> n output
forall b c a. (b -> c) -> (a -> b) -> a -> c
. resource -> m output
use) (m a -> n a
forall x. m x -> n x
f (m a -> n a) -> (output -> m a) -> output -> n a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. output -> m a
k)

instance Effect Resource where
  handle :: f ()
-> (forall x. f (m x) -> n (f x))
-> Resource m a
-> Resource n (f a)
handle state :: f ()
state handler :: forall x. f (m x) -> n (f x)
handler (Resource acquire :: m resource
acquire release :: resource -> m any
release use :: resource -> m output
use k :: output -> m a
k) = n (f resource)
-> (f resource -> n (f any))
-> (f resource -> n (f output))
-> (f output -> n (f a))
-> Resource n (f a)
forall (m :: * -> *) k resource any output.
m resource
-> (resource -> m any)
-> (resource -> m output)
-> (output -> m k)
-> Resource m k
Resource (f (m resource) -> n (f resource)
forall x. f (m x) -> n (f x)
handler (m resource
acquire m resource -> f () -> f (m resource)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ f ()
state)) (f (m any) -> n (f any)
forall x. f (m x) -> n (f x)
handler (f (m any) -> n (f any))
-> (f resource -> f (m any)) -> f resource -> n (f any)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (resource -> m any) -> f resource -> f (m any)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap resource -> m any
release) (f (m output) -> n (f output)
forall x. f (m x) -> n (f x)
handler (f (m output) -> n (f output))
-> (f resource -> f (m output)) -> f resource -> n (f output)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (resource -> m output) -> f resource -> f (m output)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap resource -> m output
use) (f (m a) -> n (f a)
forall x. f (m x) -> n (f x)
handler (f (m a) -> n (f a))
-> (f output -> f (m a)) -> f output -> n (f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (output -> m a) -> f output -> f (m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap output -> m a
k)
  handle state :: f ()
state handler :: forall x. f (m x) -> n (f x)
handler (OnError acquire :: m resource
acquire release :: resource -> m any
release use :: resource -> m output
use k :: output -> m a
k)  = n (f resource)
-> (f resource -> n (f any))
-> (f resource -> n (f output))
-> (f output -> n (f a))
-> Resource n (f a)
forall (m :: * -> *) k resource any output.
m resource
-> (resource -> m any)
-> (resource -> m output)
-> (output -> m k)
-> Resource m k
OnError  (f (m resource) -> n (f resource)
forall x. f (m x) -> n (f x)
handler (m resource
acquire m resource -> f () -> f (m resource)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ f ()
state)) (f (m any) -> n (f any)
forall x. f (m x) -> n (f x)
handler (f (m any) -> n (f any))
-> (f resource -> f (m any)) -> f resource -> n (f any)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (resource -> m any) -> f resource -> f (m any)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap resource -> m any
release) (f (m output) -> n (f output)
forall x. f (m x) -> n (f x)
handler (f (m output) -> n (f output))
-> (f resource -> f (m output)) -> f resource -> n (f output)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (resource -> m output) -> f resource -> f (m output)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap resource -> m output
use) (f (m a) -> n (f a)
forall x. f (m x) -> n (f x)
handler (f (m a) -> n (f a))
-> (f output -> f (m a)) -> f output -> n (f a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (output -> m a) -> f output -> f (m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap output -> m a
k)

-- | Provides a safe idiom to acquire and release resources safely.
--
-- When acquiring and operating on a resource (such as opening and
-- reading file handle with 'openFile' or writing to a blob of memory
-- with 'malloc'), any exception thrown during the operation may mean
-- that the resource is not properly released. @bracket acquire release op@
-- ensures that @release@ is run on the value returned from @acquire@ even
-- if @op@ throws an exception.
--
-- 'bracket' is safe in the presence of asynchronous exceptions.
bracket :: (Member Resource sig, Carrier sig m)
        => m resource           -- ^ computation to run first ("acquire resource")
        -> (resource -> m any)  -- ^ computation to run last ("release resource")
        -> (resource -> m a)    -- ^ computation to run in-between
        -> m a
bracket :: m resource -> (resource -> m any) -> (resource -> m a) -> m a
bracket acquire :: m resource
acquire release :: resource -> m any
release use :: resource -> m a
use = Resource m a -> m a
forall (effect :: (* -> *) -> * -> *) (sig :: (* -> *) -> * -> *)
       (m :: * -> *) a.
(Member effect sig, Carrier sig m) =>
effect m a -> m a
send (m resource
-> (resource -> m any)
-> (resource -> m a)
-> (a -> m a)
-> Resource m a
forall (m :: * -> *) k resource any output.
m resource
-> (resource -> m any)
-> (resource -> m output)
-> (output -> m k)
-> Resource m k
Resource m resource
acquire resource -> m any
release resource -> m a
use a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure)

-- | Like 'bracket', but only performs the final action if there was an
-- exception raised by the in-between computation.
bracketOnError :: (Member Resource sig, Carrier sig m)
               => m resource           -- ^ computation to run first ("acquire resource")
               -> (resource -> m any)  -- ^ computation to run last ("release resource")
               -> (resource -> m a)    -- ^ computation to run in-between
               -> m a
bracketOnError :: m resource -> (resource -> m any) -> (resource -> m a) -> m a
bracketOnError acquire :: m resource
acquire release :: resource -> m any
release use :: resource -> m a
use = Resource m a -> m a
forall (effect :: (* -> *) -> * -> *) (sig :: (* -> *) -> * -> *)
       (m :: * -> *) a.
(Member effect sig, Carrier sig m) =>
effect m a -> m a
send (m resource
-> (resource -> m any)
-> (resource -> m a)
-> (a -> m a)
-> Resource m a
forall (m :: * -> *) k resource any output.
m resource
-> (resource -> m any)
-> (resource -> m output)
-> (output -> m k)
-> Resource m k
OnError m resource
acquire resource -> m any
release resource -> m a
use a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure)

-- | Like 'bracket', but for the simple case of one computation to run afterward.
finally :: (Member Resource sig, Carrier sig m)
        => m a -- ^ computation to run first
        -> m b -- ^ computation to run afterward (even if an exception was raised)
        -> m a
finally :: m a -> m b -> m a
finally act :: m a
act end :: m b
end = m () -> (() -> m b) -> (() -> m a) -> m a
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) resource any a.
(Member Resource sig, Carrier sig m) =>
m resource -> (resource -> m any) -> (resource -> m a) -> m a
bracket (() -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) (m b -> () -> m b
forall a b. a -> b -> a
const m b
end) (m a -> () -> m a
forall a b. a -> b -> a
const m a
act)

-- | Like 'bracketOnError', but for the simple case of one computation to run afterward.
onException :: (Member Resource sig, Carrier sig m)
        => m a -- ^ computation to run first
        -> m b -- ^ computation to run afterward if an exception was raised
        -> m a
onException :: m a -> m b -> m a
onException act :: m a
act end :: m b
end = m () -> (() -> m b) -> (() -> m a) -> m a
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) resource any a.
(Member Resource sig, Carrier sig m) =>
m resource -> (resource -> m any) -> (resource -> m a) -> m a
bracketOnError (() -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()) (m b -> () -> m b
forall a b. a -> b -> a
const m b
end) (m a -> () -> m a
forall a b. a -> b -> a
const m a
act)

-- Not exposed due to its potential to silently drop effects (#180).
unliftResource :: (forall x . m x -> IO x) -- ^ "unlifting" function to run the carrier in 'IO'
            -> ResourceC m a
            -> m a
unliftResource :: (forall x. m x -> IO x) -> ResourceC m a -> m a
unliftResource handler :: forall x. m x -> IO x
handler = Handler m -> ReaderC (Handler m) m a -> m a
forall r (m :: * -> *) a. r -> ReaderC r m a -> m a
runReader ((forall x. m x -> IO x) -> Handler m
forall (m :: * -> *). (forall x. m x -> IO x) -> Handler m
Handler forall x. m x -> IO x
handler) (ReaderC (Handler m) m a -> m a)
-> (ResourceC m a -> ReaderC (Handler m) m a)
-> ResourceC m a
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ResourceC m a -> ReaderC (Handler m) m a
forall (m :: * -> *) a. ResourceC m a -> ReaderC (Handler m) m a
runResourceC

-- | Executes a 'Resource' effect. Because this runs using 'MonadUnliftIO',
-- invocations of 'runResource' must happen at the "bottom" of a stack of
-- effect invocations, i.e. before the use of any monads that lack such
-- instances, such as 'StateC':
--
-- @
--   runM
--   . runResource
--   . runState @Int 1
--   $ myComputation
-- @
runResource :: MonadUnliftIO m
            => ResourceC m a
            -> m a
runResource :: ResourceC m a -> m a
runResource r :: ResourceC m a
r = ((forall a. m a -> IO a) -> IO a) -> m a
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (\f :: forall a. m a -> IO a
f -> Handler m -> ResourceC m a -> IO a
forall (m :: * -> *) a. Handler m -> ResourceC m a -> IO a
runHandler ((forall a. m a -> IO a) -> Handler m
forall (m :: * -> *). (forall x. m x -> IO x) -> Handler m
Handler forall a. m a -> IO a
f) ResourceC m a
r)

newtype ResourceC m a = ResourceC { ResourceC m a -> ReaderC (Handler m) m a
runResourceC :: ReaderC (Handler m) m a }
  deriving (Applicative (ResourceC m)
ResourceC m a
Applicative (ResourceC m) =>
(forall a. ResourceC m a)
-> (forall a. ResourceC m a -> ResourceC m a -> ResourceC m a)
-> (forall a. ResourceC m a -> ResourceC m [a])
-> (forall a. ResourceC m a -> ResourceC m [a])
-> Alternative (ResourceC m)
ResourceC m a -> ResourceC m a -> ResourceC m a
ResourceC m a -> ResourceC m [a]
ResourceC m a -> ResourceC m [a]
forall a. ResourceC m a
forall a. ResourceC m a -> ResourceC m [a]
forall a. ResourceC m a -> ResourceC m a -> ResourceC m a
forall (f :: * -> *).
Applicative f =>
(forall a. f a)
-> (forall a. f a -> f a -> f a)
-> (forall a. f a -> f [a])
-> (forall a. f a -> f [a])
-> Alternative f
forall (m :: * -> *). Alternative m => Applicative (ResourceC m)
forall (m :: * -> *) a. Alternative m => ResourceC m a
forall (m :: * -> *) a.
Alternative m =>
ResourceC m a -> ResourceC m [a]
forall (m :: * -> *) a.
Alternative m =>
ResourceC m a -> ResourceC m a -> ResourceC m a
many :: ResourceC m a -> ResourceC m [a]
$cmany :: forall (m :: * -> *) a.
Alternative m =>
ResourceC m a -> ResourceC m [a]
some :: ResourceC m a -> ResourceC m [a]
$csome :: forall (m :: * -> *) a.
Alternative m =>
ResourceC m a -> ResourceC m [a]
<|> :: ResourceC m a -> ResourceC m a -> ResourceC m a
$c<|> :: forall (m :: * -> *) a.
Alternative m =>
ResourceC m a -> ResourceC m a -> ResourceC m a
empty :: ResourceC m a
$cempty :: forall (m :: * -> *) a. Alternative m => ResourceC m a
$cp1Alternative :: forall (m :: * -> *). Alternative m => Applicative (ResourceC m)
Alternative, Functor (ResourceC m)
a -> ResourceC m a
Functor (ResourceC m) =>
(forall a. a -> ResourceC m a)
-> (forall a b.
    ResourceC m (a -> b) -> ResourceC m a -> ResourceC m b)
-> (forall a b c.
    (a -> b -> c) -> ResourceC m a -> ResourceC m b -> ResourceC m c)
-> (forall a b. ResourceC m a -> ResourceC m b -> ResourceC m b)
-> (forall a b. ResourceC m a -> ResourceC m b -> ResourceC m a)
-> Applicative (ResourceC m)
ResourceC m a -> ResourceC m b -> ResourceC m b
ResourceC m a -> ResourceC m b -> ResourceC m a
ResourceC m (a -> b) -> ResourceC m a -> ResourceC m b
(a -> b -> c) -> ResourceC m a -> ResourceC m b -> ResourceC m c
forall a. a -> ResourceC m a
forall a b. ResourceC m a -> ResourceC m b -> ResourceC m a
forall a b. ResourceC m a -> ResourceC m b -> ResourceC m b
forall a b. ResourceC m (a -> b) -> ResourceC m a -> ResourceC m b
forall a b c.
(a -> b -> c) -> ResourceC m a -> ResourceC m b -> ResourceC 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 (ResourceC m)
forall (m :: * -> *) a. Applicative m => a -> ResourceC m a
forall (m :: * -> *) a b.
Applicative m =>
ResourceC m a -> ResourceC m b -> ResourceC m a
forall (m :: * -> *) a b.
Applicative m =>
ResourceC m a -> ResourceC m b -> ResourceC m b
forall (m :: * -> *) a b.
Applicative m =>
ResourceC m (a -> b) -> ResourceC m a -> ResourceC m b
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> ResourceC m a -> ResourceC m b -> ResourceC m c
<* :: ResourceC m a -> ResourceC m b -> ResourceC m a
$c<* :: forall (m :: * -> *) a b.
Applicative m =>
ResourceC m a -> ResourceC m b -> ResourceC m a
*> :: ResourceC m a -> ResourceC m b -> ResourceC m b
$c*> :: forall (m :: * -> *) a b.
Applicative m =>
ResourceC m a -> ResourceC m b -> ResourceC m b
liftA2 :: (a -> b -> c) -> ResourceC m a -> ResourceC m b -> ResourceC m c
$cliftA2 :: forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c) -> ResourceC m a -> ResourceC m b -> ResourceC m c
<*> :: ResourceC m (a -> b) -> ResourceC m a -> ResourceC m b
$c<*> :: forall (m :: * -> *) a b.
Applicative m =>
ResourceC m (a -> b) -> ResourceC m a -> ResourceC m b
pure :: a -> ResourceC m a
$cpure :: forall (m :: * -> *) a. Applicative m => a -> ResourceC m a
$cp1Applicative :: forall (m :: * -> *). Applicative m => Functor (ResourceC m)
Applicative, a -> ResourceC m b -> ResourceC m a
(a -> b) -> ResourceC m a -> ResourceC m b
(forall a b. (a -> b) -> ResourceC m a -> ResourceC m b)
-> (forall a b. a -> ResourceC m b -> ResourceC m a)
-> Functor (ResourceC m)
forall a b. a -> ResourceC m b -> ResourceC m a
forall a b. (a -> b) -> ResourceC m a -> ResourceC m b
forall (m :: * -> *) a b.
Functor m =>
a -> ResourceC m b -> ResourceC m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> ResourceC m a -> ResourceC m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> ResourceC m b -> ResourceC m a
$c<$ :: forall (m :: * -> *) a b.
Functor m =>
a -> ResourceC m b -> ResourceC m a
fmap :: (a -> b) -> ResourceC m a -> ResourceC m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> ResourceC m a -> ResourceC m b
Functor, Applicative (ResourceC m)
a -> ResourceC m a
Applicative (ResourceC m) =>
(forall a b.
 ResourceC m a -> (a -> ResourceC m b) -> ResourceC m b)
-> (forall a b. ResourceC m a -> ResourceC m b -> ResourceC m b)
-> (forall a. a -> ResourceC m a)
-> Monad (ResourceC m)
ResourceC m a -> (a -> ResourceC m b) -> ResourceC m b
ResourceC m a -> ResourceC m b -> ResourceC m b
forall a. a -> ResourceC m a
forall a b. ResourceC m a -> ResourceC m b -> ResourceC m b
forall a b. ResourceC m a -> (a -> ResourceC m b) -> ResourceC m b
forall (m :: * -> *). Monad m => Applicative (ResourceC m)
forall (m :: * -> *) a. Monad m => a -> ResourceC m a
forall (m :: * -> *) a b.
Monad m =>
ResourceC m a -> ResourceC m b -> ResourceC m b
forall (m :: * -> *) a b.
Monad m =>
ResourceC m a -> (a -> ResourceC m b) -> ResourceC 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 :: a -> ResourceC m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> ResourceC m a
>> :: ResourceC m a -> ResourceC m b -> ResourceC m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
ResourceC m a -> ResourceC m b -> ResourceC m b
>>= :: ResourceC m a -> (a -> ResourceC m b) -> ResourceC m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
ResourceC m a -> (a -> ResourceC m b) -> ResourceC m b
$cp1Monad :: forall (m :: * -> *). Monad m => Applicative (ResourceC m)
Monad, Monad (ResourceC m)
Monad (ResourceC m) =>
(forall a. String -> ResourceC m a) -> MonadFail (ResourceC m)
String -> ResourceC m a
forall a. String -> ResourceC m a
forall (m :: * -> *).
Monad m =>
(forall a. String -> m a) -> MonadFail m
forall (m :: * -> *). MonadFail m => Monad (ResourceC m)
forall (m :: * -> *) a. MonadFail m => String -> ResourceC m a
fail :: String -> ResourceC m a
$cfail :: forall (m :: * -> *) a. MonadFail m => String -> ResourceC m a
$cp1MonadFail :: forall (m :: * -> *). MonadFail m => Monad (ResourceC m)
Fail.MonadFail, Monad (ResourceC m)
Monad (ResourceC m) =>
(forall a. (a -> ResourceC m a) -> ResourceC m a)
-> MonadFix (ResourceC m)
(a -> ResourceC m a) -> ResourceC m a
forall a. (a -> ResourceC m a) -> ResourceC m a
forall (m :: * -> *).
Monad m =>
(forall a. (a -> m a) -> m a) -> MonadFix m
forall (m :: * -> *). MonadFix m => Monad (ResourceC m)
forall (m :: * -> *) a.
MonadFix m =>
(a -> ResourceC m a) -> ResourceC m a
mfix :: (a -> ResourceC m a) -> ResourceC m a
$cmfix :: forall (m :: * -> *) a.
MonadFix m =>
(a -> ResourceC m a) -> ResourceC m a
$cp1MonadFix :: forall (m :: * -> *). MonadFix m => Monad (ResourceC m)
MonadFix, Monad (ResourceC m)
Monad (ResourceC m) =>
(forall a. IO a -> ResourceC m a) -> MonadIO (ResourceC m)
IO a -> ResourceC m a
forall a. IO a -> ResourceC m a
forall (m :: * -> *).
Monad m =>
(forall a. IO a -> m a) -> MonadIO m
forall (m :: * -> *). MonadIO m => Monad (ResourceC m)
forall (m :: * -> *) a. MonadIO m => IO a -> ResourceC m a
liftIO :: IO a -> ResourceC m a
$cliftIO :: forall (m :: * -> *) a. MonadIO m => IO a -> ResourceC m a
$cp1MonadIO :: forall (m :: * -> *). MonadIO m => Monad (ResourceC m)
MonadIO, Monad (ResourceC m)
Alternative (ResourceC m)
ResourceC m a
(Alternative (ResourceC m), Monad (ResourceC m)) =>
(forall a. ResourceC m a)
-> (forall a. ResourceC m a -> ResourceC m a -> ResourceC m a)
-> MonadPlus (ResourceC m)
ResourceC m a -> ResourceC m a -> ResourceC m a
forall a. ResourceC m a
forall a. ResourceC m a -> ResourceC m a -> ResourceC m a
forall (m :: * -> *).
(Alternative m, Monad m) =>
Monad (ResourceC m)
forall (m :: * -> *).
(Alternative m, Monad m) =>
Alternative (ResourceC m)
forall (m :: * -> *).
(Alternative m, Monad m) =>
(forall a. m a) -> (forall a. m a -> m a -> m a) -> MonadPlus m
forall (m :: * -> *) a. (Alternative m, Monad m) => ResourceC m a
forall (m :: * -> *) a.
(Alternative m, Monad m) =>
ResourceC m a -> ResourceC m a -> ResourceC m a
mplus :: ResourceC m a -> ResourceC m a -> ResourceC m a
$cmplus :: forall (m :: * -> *) a.
(Alternative m, Monad m) =>
ResourceC m a -> ResourceC m a -> ResourceC m a
mzero :: ResourceC m a
$cmzero :: forall (m :: * -> *) a. (Alternative m, Monad m) => ResourceC m a
$cp2MonadPlus :: forall (m :: * -> *).
(Alternative m, Monad m) =>
Monad (ResourceC m)
$cp1MonadPlus :: forall (m :: * -> *).
(Alternative m, Monad m) =>
Alternative (ResourceC m)
MonadPlus)

instance MonadUnliftIO m => MonadUnliftIO (ResourceC m) where
  askUnliftIO :: ResourceC m (UnliftIO (ResourceC m))
askUnliftIO = ReaderC (Handler m) m (UnliftIO (ResourceC m))
-> ResourceC m (UnliftIO (ResourceC m))
forall (m :: * -> *) a. ReaderC (Handler m) m a -> ResourceC m a
ResourceC (ReaderC (Handler m) m (UnliftIO (ResourceC m))
 -> ResourceC m (UnliftIO (ResourceC m)))
-> ((Handler m -> m (UnliftIO (ResourceC m)))
    -> ReaderC (Handler m) m (UnliftIO (ResourceC m)))
-> (Handler m -> m (UnliftIO (ResourceC m)))
-> ResourceC m (UnliftIO (ResourceC m))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Handler m -> m (UnliftIO (ResourceC m)))
-> ReaderC (Handler m) m (UnliftIO (ResourceC m))
forall r (m :: * -> *) a. (r -> m a) -> ReaderC r m a
ReaderC ((Handler m -> m (UnliftIO (ResourceC m)))
 -> ResourceC m (UnliftIO (ResourceC m)))
-> (Handler m -> m (UnliftIO (ResourceC m)))
-> ResourceC m (UnliftIO (ResourceC m))
forall a b. (a -> b) -> a -> b
$ \(Handler h :: forall x. m x -> IO x
h) ->
    (UnliftIO m -> IO (UnliftIO (ResourceC m)))
-> m (UnliftIO (ResourceC m))
forall (m :: * -> *) a.
MonadUnliftIO m =>
(UnliftIO m -> IO a) -> m a
withUnliftIO ((UnliftIO m -> IO (UnliftIO (ResourceC m)))
 -> m (UnliftIO (ResourceC m)))
-> (UnliftIO m -> IO (UnliftIO (ResourceC m)))
-> m (UnliftIO (ResourceC m))
forall a b. (a -> b) -> a -> b
$ \u :: UnliftIO m
u -> UnliftIO (ResourceC m) -> IO (UnliftIO (ResourceC m))
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((forall a. ResourceC m a -> IO a) -> UnliftIO (ResourceC m)
forall (m :: * -> *). (forall a. m a -> IO a) -> UnliftIO m
UnliftIO ((forall a. ResourceC m a -> IO a) -> UnliftIO (ResourceC m))
-> (forall a. ResourceC m a -> IO a) -> UnliftIO (ResourceC m)
forall a b. (a -> b) -> a -> b
$ \r :: ResourceC m a
r -> UnliftIO m -> m a -> IO a
forall (m :: * -> *). UnliftIO m -> forall a. m a -> IO a
unliftIO UnliftIO m
u ((forall x. m x -> IO x) -> ResourceC m a -> m a
forall (m :: * -> *) a.
(forall x. m x -> IO x) -> ResourceC m a -> m a
unliftResource forall x. m x -> IO x
h ResourceC m a
r))

instance MonadTrans ResourceC where
  lift :: m a -> ResourceC m a
lift = ReaderC (Handler m) m a -> ResourceC m a
forall (m :: * -> *) a. ReaderC (Handler m) m a -> ResourceC m a
ResourceC (ReaderC (Handler m) m a -> ResourceC m a)
-> (m a -> ReaderC (Handler m) m a) -> m a -> ResourceC m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> ReaderC (Handler m) m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift

newtype Handler m = Handler (forall x . m x -> IO x)

runHandler :: Handler m -> ResourceC m a -> IO a
runHandler :: Handler m -> ResourceC m a -> IO a
runHandler h :: Handler m
h@(Handler handler :: forall x. m x -> IO x
handler) = m a -> IO a
forall x. m x -> IO x
handler (m a -> IO a) -> (ResourceC m a -> m a) -> ResourceC m a -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handler m -> ReaderC (Handler m) m a -> m a
forall r (m :: * -> *) a. r -> ReaderC r m a -> m a
runReader Handler m
h (ReaderC (Handler m) m a -> m a)
-> (ResourceC m a -> ReaderC (Handler m) m a)
-> ResourceC m a
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ResourceC m a -> ReaderC (Handler m) m a
forall (m :: * -> *) a. ResourceC m a -> ReaderC (Handler m) m a
runResourceC

instance (Carrier sig m, MonadIO m) => Carrier (Resource :+: sig) (ResourceC m) where
  eff :: (:+:) Resource sig (ResourceC m) a -> ResourceC m a
eff (L (Resource acquire :: ResourceC m resource
acquire release :: resource -> ResourceC m any
release use :: resource -> ResourceC m output
use k :: output -> ResourceC m a
k)) = do
    Handler m
handler <- ReaderC (Handler m) m (Handler m) -> ResourceC m (Handler m)
forall (m :: * -> *) a. ReaderC (Handler m) m a -> ResourceC m a
ResourceC ReaderC (Handler m) m (Handler m)
forall r (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Member (Reader r) sig, Carrier sig m) =>
m r
ask
    output
a <- IO output -> ResourceC m output
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO resource
-> (resource -> IO any) -> (resource -> IO output) -> IO output
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
Exc.bracket
      (Handler m -> ResourceC m resource -> IO resource
forall (m :: * -> *) a. Handler m -> ResourceC m a -> IO a
runHandler Handler m
handler ResourceC m resource
acquire)
      (Handler m -> ResourceC m any -> IO any
forall (m :: * -> *) a. Handler m -> ResourceC m a -> IO a
runHandler Handler m
handler (ResourceC m any -> IO any)
-> (resource -> ResourceC m any) -> resource -> IO any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. resource -> ResourceC m any
release)
      (Handler m -> ResourceC m output -> IO output
forall (m :: * -> *) a. Handler m -> ResourceC m a -> IO a
runHandler Handler m
handler (ResourceC m output -> IO output)
-> (resource -> ResourceC m output) -> resource -> IO output
forall b c a. (b -> c) -> (a -> b) -> a -> c
. resource -> ResourceC m output
use))
    output -> ResourceC m a
k output
a
  eff (L (OnError  acquire :: ResourceC m resource
acquire release :: resource -> ResourceC m any
release use :: resource -> ResourceC m output
use k :: output -> ResourceC m a
k)) = do
    Handler m
handler <- ReaderC (Handler m) m (Handler m) -> ResourceC m (Handler m)
forall (m :: * -> *) a. ReaderC (Handler m) m a -> ResourceC m a
ResourceC ReaderC (Handler m) m (Handler m)
forall r (sig :: (* -> *) -> * -> *) (m :: * -> *).
(Member (Reader r) sig, Carrier sig m) =>
m r
ask
    output
a <- IO output -> ResourceC m output
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO resource
-> (resource -> IO any) -> (resource -> IO output) -> IO output
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
Exc.bracketOnError
      (Handler m -> ResourceC m resource -> IO resource
forall (m :: * -> *) a. Handler m -> ResourceC m a -> IO a
runHandler Handler m
handler ResourceC m resource
acquire)
      (Handler m -> ResourceC m any -> IO any
forall (m :: * -> *) a. Handler m -> ResourceC m a -> IO a
runHandler Handler m
handler (ResourceC m any -> IO any)
-> (resource -> ResourceC m any) -> resource -> IO any
forall b c a. (b -> c) -> (a -> b) -> a -> c
. resource -> ResourceC m any
release)
      (Handler m -> ResourceC m output -> IO output
forall (m :: * -> *) a. Handler m -> ResourceC m a -> IO a
runHandler Handler m
handler (ResourceC m output -> IO output)
-> (resource -> ResourceC m output) -> resource -> IO output
forall b c a. (b -> c) -> (a -> b) -> a -> c
. resource -> ResourceC m output
use))
    output -> ResourceC m a
k output
a
  eff (R other :: sig (ResourceC m) a
other)                            = ReaderC (Handler m) m a -> ResourceC m a
forall (m :: * -> *) a. ReaderC (Handler m) m a -> ResourceC m a
ResourceC ((:+:) (Reader (Handler m)) sig (ReaderC (Handler m) m) a
-> ReaderC (Handler m) m a
forall (sig :: (* -> *) -> * -> *) (m :: * -> *) a.
Carrier sig m =>
sig m a -> m a
eff (sig (ReaderC (Handler m) m) a
-> (:+:) (Reader (Handler m)) sig (ReaderC (Handler m) m) a
forall (f :: (* -> *) -> * -> *) (g :: (* -> *) -> * -> *)
       (m :: * -> *) k.
g m k -> (:+:) f g m k
R (sig (ResourceC m) a -> sig (ReaderC (Handler m) m) a
forall (sig :: (* -> *) -> * -> *) (f :: * -> *) (g :: * -> *) a.
(HFunctor sig, Functor f, Coercible f g) =>
sig f a -> sig g a
handleCoercible sig (ResourceC m) a
other)))