{-# LANGUAGE CPP #-} -- | This was previously known as the Resource monad. However, that term is -- confusing next to the ResourceT transformer, so it has been renamed. module Data.Acquire ( Acquire -- * Example usage of 'Acquire' for allocating a resource and freeing it up. -- -- | The code makes use of 'mkAcquire' to create an 'Acquire' and uses 'allocateAcquire' to allocate the resource and register an action to free up the resource. -- -- === __Reproducible Stack code snippet__ -- -- > #!/usr/bin/env stack -- > {- stack -- > --resolver lts-10.0 -- > --install-ghc -- > runghc -- > --package resourcet -- > -} -- > -- > {-#LANGUAGE ScopedTypeVariables#-} -- > -- > import Data.Acquire -- > import Control.Monad.Trans.Resource -- > import Control.Monad.IO.Class -- > -- > main :: IO () -- > main = runResourceT $ do -- > let (ack :: Acquire Int) = mkAcquire (do -- > putStrLn "Enter some number" -- > readLn) (\i -> putStrLn $ "Freeing scarce resource: " ++ show i) -- > (releaseKey, resource) <- allocateAcquire ack -- > doSomethingDangerous resource -- > liftIO $ putStrLn $ "Going to release resource immediately: " ++ show resource -- > release releaseKey -- > somethingElse -- > -- > doSomethingDangerous :: Int -> ResourceT IO () -- > doSomethingDangerous i = -- > liftIO $ putStrLn $ "5 divided by " ++ show i ++ " is " ++ show (5 `div` i) -- > -- > somethingElse :: ResourceT IO () -- > somethingElse = liftIO $ putStrLn -- > "This could take a long time, don't delay releasing the resource!" -- -- Execution output: -- -- > ~ $ stack code.hs -- > Enter some number -- > 3 -- > 5 divided by 3 is 1 -- > Going to release resource immediately: 3 -- > Freeing scarce resource: 3 -- > This could take a long time, don't delay releasing the resource! -- > -- > ~ $ stack code.hs -- > Enter some number -- > 0 -- > 5 divided by 0 is Freeing scarce resource: 0 -- > code.hs: divide by zero -- , with , withAcquire , mkAcquire , mkAcquireType , allocateAcquire , ReleaseType (..) ) where import Control.Monad.Trans.Resource.Internal import Data.Acquire.Internal import Control.Monad.IO.Unlift (MonadIO (..), MonadUnliftIO) import qualified Control.Exception as E -- | Allocate a resource and register an action with the @MonadResource@ to -- free the resource. -- -- @since 1.1.0 allocateAcquire :: MonadResource m => Acquire a -> m (ReleaseKey, a) allocateAcquire :: forall (m :: * -> *) a. MonadResource m => Acquire a -> m (ReleaseKey, a) allocateAcquire = forall (m :: * -> *) a. MonadResource m => ResourceT IO a -> m a liftResourceT forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Acquire a -> ResourceT IO (ReleaseKey, a) allocateAcquireRIO allocateAcquireRIO :: Acquire a -> ResourceT IO (ReleaseKey, a) allocateAcquireRIO :: forall a. Acquire a -> ResourceT IO (ReleaseKey, a) allocateAcquireRIO (Acquire (forall b. IO b -> IO b) -> IO (Allocated a) f) = forall (m :: * -> *) a. (IORef ReleaseMap -> m a) -> ResourceT m a ResourceT forall a b. (a -> b) -> a -> b $ \IORef ReleaseMap istate -> forall (m :: * -> *) a. MonadIO m => IO a -> m a liftIO forall a b. (a -> b) -> a -> b $ forall b. ((forall b. IO b -> IO b) -> IO b) -> IO b E.mask forall a b. (a -> b) -> a -> b $ \forall b. IO b -> IO b restore -> do Allocated a a ReleaseType -> IO () free <- (forall b. IO b -> IO b) -> IO (Allocated a) f forall b. IO b -> IO b restore ReleaseKey key <- IORef ReleaseMap -> (ReleaseType -> IO ()) -> IO ReleaseKey registerType IORef ReleaseMap istate ReleaseType -> IO () free forall (m :: * -> *) a. Monad m => a -> m a return (ReleaseKey key, a a) -- | Longer name for 'with', in case @with@ is not obvious enough in context. -- -- @since 1.2.0 withAcquire :: MonadUnliftIO m => Acquire a -> (a -> m b) -> m b withAcquire :: forall (m :: * -> *) a b. MonadUnliftIO m => Acquire a -> (a -> m b) -> m b withAcquire = forall (m :: * -> *) a b. MonadUnliftIO m => Acquire a -> (a -> m b) -> m b with {-# INLINE withAcquire #-}