Maintainer | Bas van Dijk <v.dijk.bas@gmail.com> |
---|

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

- data RegionT s pr α
- runRegionT :: MonadCatchIO pr => (forall s. RegionT s pr α) -> pr α
- type TopRegion s = RegionT s IO
- runTopRegion :: (forall s. TopRegion s α) -> IO α
- forkTopRegion :: MonadIO pr => TopRegion s () -> RegionT s pr ThreadId
- class Dup α where
- module Control.Monad.Trans.Region.ParentOf
- liftCallCC :: (((α -> pr β) -> pr α) -> pr α) -> ((α -> RegionT s pr β) -> RegionT s pr α) -> RegionT s pr α
- mapRegionT :: (m α -> n β) -> RegionT s m α -> RegionT s n β
- liftCatch :: (pr α -> (e -> pr α) -> pr α) -> RegionT s pr α -> (e -> RegionT s pr α) -> RegionT s pr α

# Regions

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:

- directly executed in
`IO`

by`runTopRegion`

, - concurrently executed in a new thread by
`forkTopRegion`

.

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

Convenience funtion for running a *top-level* region in `IO`

.

Note that: `runTopRegion = `

`runRegionT`

forkTopRegion :: 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 <- 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*.

# Duplication

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`

.

# 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.