-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Provides the region monad for safely opening and working with scarce resources. -- -- This package provides the region monad transformer. Scarce resources -- like files, memory pointers or USB devices for example can be opened -- in a region. When the region terminates, all opened resources will be -- automatically closed. The main advantage of regions is that the opened -- resources can not be returned from the region which ensures no I/O -- with closed resources is possible. -- -- The primary technique used in this package is called "Lightweight -- monadic regions" which was invented by Oleg Kiselyov and Chung-chieh -- Shan. See: -- -- http://okmij.org/ftp/Haskell/regions.html#light-weight -- -- This package provides two modules: -- -- -- -- Also see the regions-monadsfd and regions-monadstf -- packages which provide instances for the classes in the respected -- monads packages. -- -- For an example of how to use this library see the -- safer-file-handles or usb-safe packages. @package regions @version 0.2 -- | WARNING: This module should not be used by end-users -- directly because it allows access to the internalHandle of a -- resource which enables them to close the resource manually, which will -- defeat the safety-guarantees that this package provides! -- -- This module should only be used by library authors wishing to -- allow their end-users to open their resources in a region. -- -- The only thing to do, to create a module or library that allows your -- users to open your resources in a region, is to define an instance for -- Resource for your type of resource. -- -- Make sure not to re-export anything from this module. Either re-export -- things from Control.Monad.Trans.Region or tell your users to -- import that module directly. module Control.Monad.Trans.Region.Unsafe -- | Class of scarce resources. A scarce resource is a resource that -- only one user can use at a time. (like a file, memory pointer or USB -- device for example). -- -- Because of the scarcity, these resources need to be opened to -- grant temporary sole access to the resource. When the resource is no -- longer needed it should be closed a.s.a.p to grant others -- access to the resource. class Resource resource where { data family Handle resource :: *; } openResource :: (Resource resource) => resource -> IO (Handle resource) closeResource :: (Resource resource) => Handle resource -> IO () -- | Get the internal handle from the regional handle. -- -- Warning: This function should not be exported to or used by -- end-users because it allows them to close the handle manually, which -- will defeat the safety-guarantees that this package provides! -- -- Tip: If you enable the ViewPatterns language extension -- you can use internalHandle as a view-pattern as in the -- following example from the usb-safe package: -- --
--   resetDevice :: (pr `ParentOf` cr, MonadIO cr)
--               -> RegionalHandle USB.Device pr -> cr ()
--   resetDevice (internalHandle -> (DeviceHandle ...)) = ...
--   
internalHandle :: RegionalHandle resource r -> Handle resource -- | Duplicate an α in the parent region. This α will -- usually be a (RegionalHandle resource) but it -- can be any value "derived" from this regional handle. -- -- For example, suppose you run the following region: -- --
--   runRegionT $ do
--   
-- -- Inside this region you run a nested child region like: -- --
--   r1hDup <- runRegionT $ do
--   
-- -- Now in this child region you open the resource r1: -- --
--   r1h <- open r1
--   
-- -- ...yielding the regional handle r1h. Note that: -- --
--   r1h :: RegionalHandle resource (RegionT cs (RegionT ps ppr))
--   
-- -- where cs is bound by the inner (child) runRegionT -- and ps is bound by the outer (parent) runRegionT. -- -- Suppose you want to use the resulting regional handle r1h in -- the parent region. You can't simply return r1h because -- then the type variable cs, escapes the inner region. -- -- However, if you duplicate the regional handle you can safely return -- it. -- --
--   r1hDup <- dup r1h
--   return r1hDup
--   
-- -- Note that r1hDup :: RegionalHandle resource (RegionT ps ppr) -- -- Back in the parent region you can safely operate on r1hDup. class Dup α dup :: (Dup α, MonadCatchIO ppr) => α (RegionT cs (RegionT ps ppr)) -> RegionT cs (RegionT ps ppr) (α (RegionT ps ppr)) -- | The ParentOf class declares the parent/child relationship -- between regions. -- -- A region is the parent of another region if they're either equivalent -- like: -- --
--   RegionT ps pr  `ParentOf`  RegionT ps pr
--   
-- -- or if it is the parent of the parent of the child like: -- --
--   RegionT ps ppr `ParentOf` RegionT cs
--                                 (RegionT pcs
--                                   (RegionT ppcs
--                                     (RegionT ps ppr)))
--   
class (Monad pr, Monad cr) => ParentOf pr cr -- | This modules implements a technique called "Lightweight monadic -- regions" invented by Oleg Kiselyov and Chung-chieh Shan -- -- See: http://okmij.org/ftp/Haskell/regions.html#light-weight module Control.Monad.Trans.Region -- | A monad transformer in which scarce resources can be opened which are -- automatically closed when the region terminates. -- -- Note that regions can be nested. pr (for parent region) is a -- monad which is usually the region which is running this region. -- However when you are running a TopRegion the parent region will -- be IO. data RegionT s pr :: (* -> *) α -- | Execute a region inside its parent region pr. -- -- All resources which have been opened in the given region using -- open, and which haven't been duplicated using dup, will -- be closed on exit from this function wether by normal termination or -- by raising an exception. -- -- Also all resources which have been duplicated to this region from a -- child region are closed on exit if they haven't been duplicated -- themselves. -- -- Note the type variable s of the region wich is only -- quantified over the region itself. This ensures that all -- values, having a type containing s, can not be -- returned from this function. (Note the similarity with the ST -- monad.) -- -- An example of such a value is a RegionalHandle. Regional -- handles are created by opening a resource in a region using -- open. Regional handles are parameterized by the region in which -- they were created. So regional handles have this s in their -- type. This ensures that these regional handles, which may have been -- closed on exit from this function, can't be returned from this -- function. This ensures you can never do any IO with a closed regional -- handle. -- -- Note that it is possible to run a region inside another region. runRegionT :: (MonadCatchIO pr) => (forall s. RegionT s pr α) -> pr α -- | A region which has IO as its parent region which enables it to -- be: -- -- type TopRegion s = RegionT s IO -- | Convenience funtion for running a top-level region in -- IO. -- -- Note that: runTopRegion = runRegionT runTopRegion :: (forall s. TopRegion s α) -> IO α -- | Return a region which executes the given top-level region in a -- new thread. -- -- Note that the forked region has the same type variable s as -- the resulting region. This means that all values which can be -- referenced in the resulting region (like RegionalHandles for -- example) can also be referenced in the forked region. -- -- For example the following is allowed: -- --
--   runRegionT $ do
--     regionalHndl <- open resource
--     threadId <- forkTopRegion $ doSomethingWith regionalHndl
--     doSomethingElseWith regionalHndl
--   
-- -- Note that the regionalHndl and all other resources opened in -- the current thread are closed only when the current thread or the -- forked thread terminates whichever comes last. forkTopRegion :: (MonadIO pr) => TopRegion s () -> RegionT s pr ThreadId -- | A handle to an opened resource parameterized by the resource -- and the region r in which it was created. data RegionalHandle resource r :: (* -> *) -- | Open the given resource in a region yielding a regional handle to it. -- -- Note that the returned regional handle is parameterized by the region -- in which it was created. This ensures that regional handles can never -- escape their region. And it also allows operations on regional handles -- to be executed in a child region of the region in which the regional -- handle was created. -- -- Note that if you do wish to return a regional handle from the -- region in which it was created you have to duplicate the handle -- by applying dup to it. open :: (Resource resource, MonadCatchIO pr) => resource -> RegionT s pr (RegionalHandle resource (RegionT s pr)) -- | A convenience function which opens the given resource, applies the -- given continuation function to the resulting regional handle and runs -- the resulting region. -- -- Note that: with dev f = runRegionT -- (open dev >>= f) with :: (Resource resource, MonadCatchIO pr) => resource -> (forall s. RegionalHandle resource (RegionT s pr) -> RegionT s pr α) -> pr α dup :: (Dup α, MonadCatchIO ppr) => α (RegionT cs (RegionT ps ppr)) -> RegionT cs (RegionT ps ppr) (α (RegionT ps ppr)) -- | Transform the computation inside a region. mapRegionT :: (m α -> n β) -> RegionT s m α -> RegionT s n β -- | Lift a catchError operation to the new monad. liftCatch :: (pr α -> (e -> pr α) -> pr α) -> RegionT s pr α -> (e -> RegionT s pr α) -> RegionT s pr α