regions-0.1.0.1: Provides the region monad for safely opening and working with scarce resources.Source codeContentsIndex
Control.Monad.Trans.Region.Internal
MaintainerBas van Dijk <v.dijk.bas@gmail.com>
Contents
Scarce resources
Regions
Running regions
Opening resources
Duplication
Handy functions for writing monadic instances
Parent/child relationship between regions.
Description

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

This module should only be used by library authors wishing to allow their users to open their type of resources in a region. It should not be used by end-users directly!

To create a module or library that allows your users to open your type of 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.

Synopsis
class Resource resource where
data Handle resource :: *
openResource :: resource -> IO (Handle resource)
closeResource :: Handle resource -> IO ()
data RegionT resource s pr α
runRegionT :: (Resource resource, MonadCatchIO pr) => (forall s. RegionT resource s pr α) -> pr α
type TopRegion resource s = RegionT resource s IO
runTopRegion :: Resource resource => (forall s. TopRegion resource s α) -> IO α
forkTopRegion :: (Resource resource, MonadIO pr) => TopRegion resource s () -> RegionT resource s pr ThreadId
data RegionalHandle resource r
internalHandle :: RegionalHandle resource r -> Handle resource
open :: (Resource resource, MonadCatchIO pr) => resource -> RegionT resource s pr (RegionalHandle resource (RegionT resource s pr))
with :: (Resource resource, MonadCatchIO pr) => resource -> (forall s. RegionalHandle resource (RegionT resource s pr) -> RegionT resource s pr α) -> pr α
class Resource resource => Dup α resource where
dup :: MonadCatchIO ppr => α (RegionT resource cs (RegionT resource ps ppr)) -> RegionT resource cs (RegionT resource ps ppr) (α (RegionT resource ps ppr))
mapRegionT :: (m α -> n β) -> RegionT resource s m α -> RegionT resource s n β
liftCatch :: (pr α -> (e -> pr α) -> pr α) -> RegionT resource s pr α -> (e -> RegionT resource s pr α) -> RegionT resource s pr α
class (Monad pr, Monad cr) => ParentOf pr cr
Scarce resources
class Resource resource whereSource

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.

Associated Types
data Handle resource :: *Source
Methods
openResource :: resource -> IO (Handle resource)Source
closeResource :: Handle resource -> IO ()Source
Regions
data RegionT resource s pr α Source

A monad transformer in which resources of type resource 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.

show/hide Instances
MonadTrans (RegionT resource s)
Monad pr => Monad (RegionT resource s pr)
Functor pr => Functor (RegionT resource s pr)
MonadFix pr => MonadFix (RegionT resource s pr)
MonadPlus pr => MonadPlus (RegionT resource s pr)
Applicative pr => Applicative (RegionT resource s pr)
MonadCatchIO pr => MonadCatchIO (RegionT resource s pr)
Alternative pr => Alternative (RegionT resource s pr)
MonadIO pr => MonadIO (RegionT resource s pr)
Running regions
runRegionTSource
:: (Resource resource, MonadCatchIO pr)
=> forall s. RegionT resource s pr αComputation in the parent region which executes the given region.
-> 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.

type TopRegion resource s = RegionT resource s IOSource

A region which has IO as its parent region which enables it to be:

runTopRegionSource
:: Resource resource
=> forall s. TopRegion resource s αAn IO computation which executes the given region.
-> IO α

Convenience funtion for running a top-level region in IO.

Note that: runTopRegion = runRegionT

forkTopRegionSource
:: (Resource resource, MonadIO pr)
=> TopRegion resource s ()A regional computation that executes the given region in a new thread and returns the ThreadId of this new thread.
-> RegionT resource s pr ThreadId

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.

Opening resources
data RegionalHandle resource r Source
A handle to an opened resource parameterized by the resource and the region r in which it was created.
show/hide Instances
Resource resource => Dup (RegionalHandle resource) resource
internalHandle :: RegionalHandle resource r -> Handle resourceSource

Get the internal handle from the regional handle.

Warning: This function should not be exported to end-users because it allows them to close the handle manually!

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 ...)) = ...
openSource
:: (Resource resource, MonadCatchIO pr)
=> resourceA regional computation that returns a regional handle to the given opened resource parameterized by the region itself.
-> RegionT resource s pr (RegionalHandle resource (RegionT resource s pr))

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.

withSource
:: (Resource resource, MonadCatchIO pr)
=> resourceContinuation function.
-> forall s. RegionalHandle resource (RegionT resource s pr) -> RegionT resource s pr αA computation which runs a child region which opens the given resource and applies the given continuation function to the resulting regional handle.
-> 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)

Duplication
class Resource resource => Dup α resource whereSource

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 resource cs (RegionT resource 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 device 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 resource ps ppr)

Back in the parent region you can safely operate on r1hDup.

Methods
dupSource
:: MonadCatchIO ppr
=> α (RegionT resource cs (RegionT resource ps ppr))The child region which returns the thing which can now be used in the parent region.
-> RegionT resource cs (RegionT resource ps ppr) (α (RegionT resource ps ppr))
show/hide Instances
Resource resource => Dup (RegionalHandle resource) resource
Handy functions for writing monadic instances
mapRegionT :: (m α -> n β) -> RegionT resource s m α -> RegionT resource s n βSource
Transform the computation inside a region.
liftCatchSource
::
=> pr α -> (e -> pr α) -> pr αComputation to attempt.
-> RegionT resource s pr αException handler.
-> e -> RegionT resource s pr α
-> RegionT resource s pr α
Lift a catchError operation to the new monad.
TODO: define and export: liftCallCC
Parent/child relationship between regions.
class (Monad pr, Monad cr) => ParentOf pr cr Source

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 resource ps pr  `ParentOf`  RegionT resource ps pr

or if it is the parent of the parent of the child like:

RegionT resource ps ppr `ParentOf` RegionT resource cs
                                     (RegionT resource pcs
                                       (RegionT resource ppcs
                                         (RegionT resource ps ppr)))
show/hide Instances
(Monad cr, TypeCast2 cr (RegionT resource s pcr), ParentOf pr pcr) => ParentOf pr cr
Monad r => ParentOf r r
Produced by Haddock version 2.6.0