{-# LANGUAGE CPP #-} {-# LANGUAGE Safe #-} -- | 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 , withEx , mkAcquire , mkAcquireType , allocateAcquire , ReleaseType (..) ) where import Control.Monad.Trans.Resource.Internal import Control.Monad.Trans.Resource import Data.Acquire.Internal import Control.Applicative (Applicative (..)) import Control.Monad.Base (MonadBase (..)) import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Trans.Control (MonadBaseControl, control) import qualified Control.Exception.Lifted as E import Data.Typeable (Typeable) import Control.Monad (liftM, ap) -- | 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 = liftResourceT . allocateAcquireRIO allocateAcquireRIO :: Acquire a -> ResourceT IO (ReleaseKey, a) allocateAcquireRIO (Acquire f) = ResourceT $ \istate -> liftIO $ E.mask $ \restore -> do Allocated a free <- f restore key <- registerType istate free return (key, a)