regions- Provides the region monad for safely opening and working with scarce resources.

MaintainerBas van Dijk <>




This modules implements a technique called "Lightweight monadic regions" invented by Oleg Kiselyov and Chung-chieh Shan




data RegionT s pr α Source

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.


MonadTrans (RegionT s) 
Monad pr => Monad (RegionT s pr) 
Functor pr => Functor (RegionT s pr) 
MonadFix pr => MonadFix (RegionT s pr) 
MonadPlus pr => MonadPlus (RegionT s pr) 
Applicative pr => Applicative (RegionT s pr) 
MonadCatchIO pr => MonadCatchIO (RegionT s pr) 
Alternative pr => Alternative (RegionT s pr) 
MonadIO pr => MonadIO (RegionT s pr) 

Running regions

runRegionT :: MonadCatchIO pr => (forall s. RegionT s pr α) -> pr αSource

Execute a region inside its parent region pr.

All resources which have been opened in the given region 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.)

Note that it is possible to run a region inside another region.

type TopRegion s = RegionT s IOSource

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

runTopRegion :: (forall s. TopRegion s α) -> IO αSource

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

Note that: runTopRegion = runRegionT

Forking top-level regions

forkIOTopRegion :: MonadIO pr => TopRegion s () -> RegionT s pr ThreadIdSource

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 can also be referenced in the forked region.

For example the following is allowed:

runRegionT $ do
  regionalHndl <- open resource
  threadId <- forkIOTopRegion $ 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.

forkOSTopRegion :: MonadIO pr => TopRegion s () -> RegionT s pr ThreadIdSource

Like forkIOTopRegion but internally uses forkOS.

forkOnIOTopRegion :: MonadIO pr => Int -> TopRegion s () -> RegionT s pr ThreadIdSource

Like forkIOTopRegion but internally uses forkOnIO.


class Dup α whereSource

Duplicate an α in the parent region. This α will usually be some type of 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 (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 (RegionT ps ppr)

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


dup :: MonadCatchIO ppr => α (RegionT cs (RegionT ps ppr)) -> RegionT cs (RegionT ps ppr) (α (RegionT ps ppr))Source


Handy functions for writing monadic instances

liftCallCC :: (((α -> pr β) -> pr α) -> pr α) -> ((α -> RegionT s pr β) -> RegionT s pr α) -> RegionT s pr αSource

Lift a callCC operation to the new monad.

mapRegionT :: (m α -> n β) -> RegionT s m α -> RegionT s n βSource

Transform the computation inside a region.

liftCatch :: (pr α -> (e -> pr α) -> pr α) -> RegionT s pr α -> (e -> RegionT s pr α) -> RegionT s pr αSource

Lift a catchError operation to the new monad.