Stability experimental Bas van Dijk Safe-Infered

Description

(TODO: It would be nicer if the associated data types `StT` and `StM` were associated type synonyms instead. This would simplify a lot of code and could make some definitions more efficient because there'll be no need to wrap the monadic state in a data type. Unfortunately GHC has a bug which prevents this: http://hackage.haskell.org/trac/ghc/ticket/5595. I will switch to associated type synonyms when that bug is fixed.)

Synopsis

# Documentation

Associated Types

data StT t :: * -> *Source

Monadic state of `t`.

Methods

liftWith :: Monad m => (Run t -> m a) -> t m aSource

`liftWith` is similar to `lift` in that it lifts a computation from the argument monad to the constructed monad.

Instances should satisfy similar laws as the `MonadTrans` laws:

`liftWith . const . return = return`
`liftWith (const (m >>= f)) = liftWith (const m) >>= liftWith . const . f`

The difference with `lift` is that before lifting the `m` computation `liftWith` captures the state of `t`. It then provides the `m` computation with a `Run` function that allows running `t n` computations in `n` (for all `n`) on the captured state.

restoreT :: Monad m => m (StT t a) -> t m aSource

Construct a `t` computation from the monadic state of `t` that is returned from a `Run` function.

Instances should satisfy:

`liftWith (\run -> run t) >>= restoreT . return = t`

Instances

type Run t = forall n b. Monad n => t n b -> n (StT t b)Source

A function that runs a transformed monad `t n` on the monadic state that was captured by `liftWith`

A `Run t` function yields a computation in `n` that returns the monadic state of `t`. This state can later be used to restore a `t` computation using `restoreT`.

class MonadBase b m => MonadBaseControl b m | m -> b whereSource

Associated Types

data StM m :: * -> *Source

Monadic state of `m`.

Methods

liftBaseWith :: (RunInBase m b -> b a) -> m aSource

`liftBaseWith` is similar to `liftIO` and `liftBase` in that it lifts a base computation to the constructed monad.

Instances should satisfy similar laws as the `MonadIO` and `MonadBase` laws:

`liftBaseWith . const . return = return`
`liftBaseWith (const (m >>= f)) = liftBaseWith (const m) >>= liftBaseWith . const . f`

The difference with `liftBase` is that before lifting the base computation `liftBaseWith` captures the state of `m`. It then provides the base computation with a `RunInBase` function that allows running `m` computations in the base monad on the captured state.

restoreM :: StM m a -> m aSource

Construct a `m` computation from the monadic state of `m` that is returned from a `RunInBase` function.

Instances should satisfy:

`liftBaseWith (\runInBase -> runInBase m) >>= restoreM = m`

Instances

type RunInBase m b = forall a. m a -> b (StM m a)Source

A function that runs a `m` computation on the monadic state that was captured by `liftBaseWith`

A `RunInBase m` function yields a computation in the base monad of `m` that returns the monadic state of `m`. This state can later be used to restore the `m` computation using `restoreM`.

Note that by using the following default definitions it's easy to make a monad transformer `T` an instance of `MonadBaseControl`:

``` instance MonadBaseControl b m => MonadBaseControl b (T m) where
newtype StM (T m) a = StMT {unStMT :: `ComposeSt` T m a}
liftBaseWith = `defaultLiftBaseWith` StMT
restoreM     = `defaultRestoreM`   unStMT
```

Defining an instance for a base monad `B` is equally straightforward:

``` instance MonadBaseControl B B where
newtype StM B a = StMB {unStMB :: a}
liftBaseWith f  = f \$ liftM  StMB
restoreM        = return . unStMB
```

type ComposeSt t m a = StM m (StT t a)Source

Handy type synonym that composes the monadic states of `t` and `m`.

It can be used to define the `StM` for new `MonadBaseControl` instances.

Arguments

 :: (MonadTransControl t, MonadBaseControl b m) => (forall c. ComposeSt t m c -> StM (t m) c) `StM` constructor -> (RunInBase (t m) b -> b a) -> t m a

Default defintion for the `liftBaseWith` method.

Note that it composes a `liftWith` of `t` with a `liftBaseWith` of `m` to give a `liftBaseWith` of `t m`:

``` defaultLiftBaseWith stM = \f -> `liftWith` \$ \run ->
`liftBaseWith` \$ \runInBase ->
f \$ liftM stM . runInBase . run
```

Arguments

 :: (MonadTransControl t, MonadBaseControl b m) => (StM (t m) a -> ComposeSt t m a) `StM` deconstructor -> StM (t m) a -> t m a

Default definition for the `restoreM` method.

Note that: `defaultRestoreM unStM = restoreT . restoreM . unStM`

# Utility functions

control :: MonadBaseControl b m => (RunInBase m b -> b (StM m a)) -> m aSource

An often used composition: `control f = liftBaseWith f >>= restoreM`

liftBaseOp :: MonadBaseControl b m => ((a -> b (StM m c)) -> b (StM m d)) -> (a -> m c) -> m dSource

`liftBaseOp` is a particular application of `liftBaseWith` that allows lifting control operations of type:

`((a -> b c) -> b c)` to: `(MonadBaseControl b m => (a -> m c) -> m c)`.

For example:

`liftBaseOp alloca :: `MonadBaseControl` `IO` m => (Ptr a -> m c) -> m c`

liftBaseOp_ :: MonadBaseControl b m => (b (StM m a) -> b (StM m c)) -> m a -> m cSource

`liftBaseOp_` is a particular application of `liftBaseWith` that allows lifting control operations of type:

`(b a -> b a)` to: `(MonadBaseControl b m => m a -> m a)`.

For example:

`liftBaseOp_ mask_ :: `MonadBaseControl` `IO` m => m a -> m a`

liftBaseDiscard :: MonadBaseControl b m => (b () -> b a) -> m () -> m aSource

`liftBaseDiscard` is a particular application of `liftBaseWith` that allows lifting control operations of type:

`(b () -> b a)` to: `(MonadBaseControl b m => m () -> m a)`.

Note that, while the argument computation `m ()` has access to the captured state, all its side-effects in `m` are discarded. It is run only for its side-effects in the base monad `b`.

For example:

`liftBaseDiscard forkIO :: `MonadBaseControl` `IO` m => m () -> m ThreadId`