-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A monad for managed values -- -- In Haskell you very often acquire values using the with... -- idiom using functions of type (a -> IO r) -> IO r. This -- idiom forms a Monad, which is a special case of the -- ContT monad (from transformers) or the -- Codensity monad (from kan-extensions). The main -- purpose behind this package is to provide a restricted form of these -- monads specialized to this unusually common case. -- -- The reason this package defines a specialized version of these types -- is to: -- --
-- main = -- withFile "inFile.txt" ReadMode $ \inHandle -> -- withFile "outFile.txt" WriteMode $ \outHandle -> -- copy inHandle outHandle -- -- -- A hypothetical function that copies data from one handle to another -- copy :: Handle -> Handle -> IO () ---- -- withFile is one of many functions that acquire some resource in -- an exception-safe way. These functions take a callback function as an -- argument and they invoke the callback on the resource when it becomes -- available, guaranteeing that the resource is properly disposed if the -- callback throws an exception. -- -- These functions usually have a type that ends with the following -- pattern: -- --
-- Callback -- -- ----------- -- withXXX :: ... -> (a -> IO r) -> IO r ---- -- Here are some examples of this pattern from the base -- libraries: -- --
-- withArray :: Storable a => [a] -> (Ptr a -> IO r) -> IO r -- withBuffer :: Buffer e -> (Ptr e -> IO r) -> IO r -- withCAString :: String -> (CString -> IO r) -> IO r -- withForeignPtr :: ForeignPtr a -> (Ptr a -> IO r) -> IO r -- withMVar :: Mvar a -> (a -> IO r) -> IO r -- withPool :: (Pool -> IO r) -> IO r ---- -- Acquiring multiple resources in this way requires nesting callbacks. -- However, you can wrap anything of the form ((a -> IO r) -> -- IO r) in the Managed monad, which translates binds to -- callbacks for you: -- --
-- import Control.Monad.Managed -- import System.IO -- -- inFile :: FilePath -> Managed Handle -- inFile filePath = managed (withFile filePath ReadMode) -- -- outFile :: FilePath -> Managed Handle -- outFile filePath = managed (withFile filePath WriteMode) -- -- main = runManaged $ do -- inHandle <- inFile "inFile.txt" -- outHandle <- outFile "outFile.txt" -- liftIO (copy inHandle outHandle) ---- -- ... or you can just wrap things inline: -- --
-- main = runManaged $ do -- inHandle <- managed (withFile "inFile.txt" ReadMode) -- outHandle <- managed (withFile "outFile.txt" WriteMode) -- liftIO (copy inHandle outHandle) ---- -- Additionally, since Managed is a Monad, you can take -- advantage of all your favorite combinators from Control.Monad. -- For example, the withMany function from -- Foreign.Marshal.Utils becomes a trivial wrapper around -- mapM: -- --
-- withMany :: (a -> (b -> IO r) -> IO r) -> [a] -> ([b] -> IO r) -> IO r -- withMany f = with . mapM (Managed . f) ---- -- Another reason to use Managed is that if you wrap a -- Monoid value in Managed you get back a new -- Monoid: -- --
-- instance Monoid a => Monoid (Managed a) ---- -- This lets you combine managed resources transparently. You can also -- lift operations from some numeric type classes this way, too, such as -- the Num type class. -- -- NOTE: Managed may leak space if used in an infinite loop like -- this example: -- --
-- import Control.Monad -- import Control.Monad.Managed -- -- main = runManaged (forever (liftIO (print 1))) ---- -- If you need to acquire a resource for a long-lived loop, you can -- instead acquire the resource first and run the loop in IO, -- using either of the following two equivalent idioms: -- --
-- with resource (\r -> forever (useThe r)) -- -- do r <- resource -- liftIO (forever (useThe r)) --module Control.Monad.Managed -- | A managed resource that you acquire using with data Managed a -- | You can embed a Managed action within any Monad that -- implements MonadManaged by using the using function -- -- All instances must obey the following two laws: -- --
-- using (return x) = return x -- -- using (m >>= f) = using m >>= \x -> using (f x) --class MonadIO m => MonadManaged m using :: MonadManaged m => Managed a -> m a -- | Build a Managed value managed :: (forall r. (a -> IO r) -> IO r) -> Managed a -- | Like managed but for resource-less operations. managed_ :: (forall r. IO r -> IO r) -> Managed () -- | Acquire a Managed value -- -- This is a potentially unsafe function since it allows a resource to -- escape its scope. For example, you might use Managed to safely -- acquire a file handle, like this: -- --
-- import qualified System.IO as IO -- -- example :: Managed Handle -- example = managed (IO.withFile "foo.txt" IO.ReadMode) ---- -- ... and if you never used the with function then you would -- never run the risk of accessing the Handle after the file was -- closed. However, if you use with then you can incorrectly -- access the handle after the handle is closed, like this: -- --
-- bad :: IO () -- bad = do -- handle <- with example return -- IO.hPutStrLn handle "bar" -- This will fail because the handle is closed ---- -- ... so only use with if you know what you are doing and you're -- returning a value that is not a resource being managed. with :: Managed a -> (a -> IO r) -> IO r -- | Run a Managed computation, enforcing that no acquired resources -- leak runManaged :: Managed () -> IO () -- | Monads in which IO computations may be embedded. Any monad -- built by applying a sequence of monad transformers to the IO -- monad will be an instance of this class. -- -- Instances should satisfy the following laws, which state that -- liftIO is a transformer of monads: -- -- class Monad m => MonadIO (m :: Type -> Type) -- | Lift a computation from the IO monad. liftIO :: MonadIO m => IO a -> m a instance Control.Monad.Managed.MonadManaged Control.Monad.Managed.Managed instance Control.Monad.Managed.MonadManaged m => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.Cont.ContT r m) instance Control.Monad.Managed.MonadManaged m => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.Except.ExceptT e m) instance Control.Monad.Managed.MonadManaged m => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.Identity.IdentityT m) instance Control.Monad.Managed.MonadManaged m => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.Maybe.MaybeT m) instance Control.Monad.Managed.MonadManaged m => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.Reader.ReaderT r m) instance (GHC.Base.Monoid w, Control.Monad.Managed.MonadManaged m) => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.RWS.Lazy.RWST r w s m) instance (GHC.Base.Monoid w, Control.Monad.Managed.MonadManaged m) => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.RWS.Strict.RWST r w s m) instance Control.Monad.Managed.MonadManaged m => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.State.Strict.StateT s m) instance Control.Monad.Managed.MonadManaged m => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.State.Lazy.StateT s m) instance (GHC.Base.Monoid w, Control.Monad.Managed.MonadManaged m) => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.Writer.Strict.WriterT w m) instance (GHC.Base.Monoid w, Control.Monad.Managed.MonadManaged m) => Control.Monad.Managed.MonadManaged (Control.Monad.Trans.Writer.Lazy.WriterT w m) instance GHC.Base.Functor Control.Monad.Managed.Managed instance GHC.Base.Applicative Control.Monad.Managed.Managed instance GHC.Base.Monad Control.Monad.Managed.Managed instance Control.Monad.IO.Class.MonadIO Control.Monad.Managed.Managed instance Control.Monad.Fail.MonadFail Control.Monad.Managed.Managed instance GHC.Base.Semigroup a => GHC.Base.Semigroup (Control.Monad.Managed.Managed a) instance GHC.Base.Monoid a => GHC.Base.Monoid (Control.Monad.Managed.Managed a) instance GHC.Num.Num a => GHC.Num.Num (Control.Monad.Managed.Managed a) instance GHC.Real.Fractional a => GHC.Real.Fractional (Control.Monad.Managed.Managed a) instance GHC.Float.Floating a => GHC.Float.Floating (Control.Monad.Managed.Managed a) -- | This module is a safer subset of Control.Monad.Managed that -- only lets you unwrap the Managed type using runManaged. -- This enforces that you never leak acquired resources from a -- Managed computation. -- -- In general, you should strive to propagate the Managed type as -- much as possible and use runManaged when you are done with -- acquired resources. However, there are legitimate circumstances where -- you want to return a value other than acquired resource from the -- bracketed computation, which requires using with. -- -- This module is not the default because you can also use the -- Managed type for callback-based code that is completely -- unrelated to resources. module Control.Monad.Managed.Safe -- | A managed resource that you acquire using with data Managed a -- | You can embed a Managed action within any Monad that -- implements MonadManaged by using the using function -- -- All instances must obey the following two laws: -- --
-- using (return x) = return x -- -- using (m >>= f) = using m >>= \x -> using (f x) --class MonadIO m => MonadManaged m using :: MonadManaged m => Managed a -> m a -- | Build a Managed value managed :: (forall r. (a -> IO r) -> IO r) -> Managed a -- | Like managed but for resource-less operations. managed_ :: (forall r. IO r -> IO r) -> Managed () -- | Run a Managed computation, enforcing that no acquired resources -- leak runManaged :: Managed () -> IO () -- | Monads in which IO computations may be embedded. Any monad -- built by applying a sequence of monad transformers to the IO -- monad will be an instance of this class. -- -- Instances should satisfy the following laws, which state that -- liftIO is a transformer of monads: -- -- class Monad m => MonadIO (m :: Type -> Type) -- | Lift a computation from the IO monad. liftIO :: MonadIO m => IO a -> m a