st2-0.1.0.0: shared heap regions between local mutable state threads

Safe HaskellNone
LanguageHaskell2010

Control.Monad.ST2

Contents

Description

This library implements the ST2 monad, a type using GDP (ghosts of departed proofs) to define shared regions of memory between local mutable state threads. This allows us to define a region of the heap in more minute contours, with each state thread having explicit access to regions in memory. This is achieved using the function runST2, which in effects lets the user run a computation that makes use of two partially-overlapping memory regions. Within that computation, the user can run sub-computations bound to one or the other memory region. Furthermore, a sub-computation can move any variable that it owns into the common overlap via share.

An example is shown in below, where one sub-computation creates two cells: one private, and the other shared. A second sub-computation has unconstrained access to the shared cell. Yet even though the private reference is also in scope during the second sub-computation, any attempts to access it there will fail to compile.

>>> :{
stSharingDemo :: Bool
stSharingDemo = runST2 $ do
  -- In the "left" memory region, create and return
  -- two references; one shared, and one not shared.
  (secret, ref) <- liftL $ do
    unshared <- newSTRef 42
    shared   <- share =<< newSTRef 17
    return (unshared, shared)
  -- In the "right" memory region, mutate the shared
  -- reference. If we attempt to access the non-shared
  -- reference here, the program will not compile.
  liftR $ do
    let mine = use (symm ref)
    x <- readSTRef mine
    writeSTRef mine (x + 1)
  -- Back in the "left" memory region, verify that the
  -- unshared reference still holds its original value.
  liftL $ do
    check <- readSTRef secret
    return (check == 42) 
:}
Synopsis

ST2 API

newtype ST s a Source #

The strict state-transformer monad. A computation of type ST s a transforms an internal state indexed by s, and returns a value of type a. The s parameter is either

  • an uninstantiated type variable (inside invocations of runST), or
  • RealWorld (inside invocations of stToIO).

It serves to keep the internal states of different invocations of runST separate from each other and from invocations of stToIO.

The >>= and >> operations are strict in the state (though not in values stored in the state). For example,

runST (writeSTRef _|_ v >>= f) = _|_

Constructors

ST (STRep (Any ~~ s) a) 
Instances
Monad (ST s) Source # 
Instance details

Defined in Control.Monad.ST2

Methods

(>>=) :: ST s a -> (a -> ST s b) -> ST s b #

(>>) :: ST s a -> ST s b -> ST s b #

return :: a -> ST s a #

fail :: String -> ST s a #

Functor (ST s) Source # 
Instance details

Defined in Control.Monad.ST2

Methods

fmap :: (a -> b) -> ST s a -> ST s b #

(<$) :: a -> ST s b -> ST s a #

Applicative (ST s) Source # 
Instance details

Defined in Control.Monad.ST2

Methods

pure :: a -> ST s a #

(<*>) :: ST s (a -> b) -> ST s a -> ST s b #

liftA2 :: (a -> b -> c) -> ST s a -> ST s b -> ST s c #

(*>) :: ST s a -> ST s b -> ST s b #

(<*) :: ST s a -> ST s b -> ST s a #

PrimMonad (ST s) Source # 
Instance details

Defined in Control.Monad.ST2

Associated Types

type PrimState (ST s) :: * #

Methods

primitive :: (State# (PrimState (ST s)) -> (#State# (PrimState (ST s)), a#)) -> ST s a #

PrimBase (ST s) Source # 
Instance details

Defined in Control.Monad.ST2

Methods

internal :: ST s a -> State# (PrimState (ST s)) -> (#State# (PrimState (ST s)), a#) #

Show (ST s a) Source # 
Instance details

Defined in Control.Monad.ST2

Methods

showsPrec :: Int -> ST s a -> ShowS #

show :: ST s a -> String #

showList :: [ST s a] -> ShowS #

Semigroup a => Semigroup (ST s a) Source # 
Instance details

Defined in Control.Monad.ST2

Methods

(<>) :: ST s a -> ST s a -> ST s a #

sconcat :: NonEmpty (ST s a) -> ST s a #

stimes :: Integral b => b -> ST s a -> ST s a #

Monoid a => Monoid (ST s a) Source # 
Instance details

Defined in Control.Monad.ST2

Methods

mempty :: ST s a #

mappend :: ST s a -> ST s a -> ST s a #

mconcat :: [ST s a] -> ST s a #

type PrimState (ST s) Source # 
Instance details

Defined in Control.Monad.ST2

type PrimState (ST s) = s

type STRep s a = State# s -> (#State# s, a#) Source #

Convenience type alias for expressing ST computations more succintly.

fixST :: (a -> ST s a) -> ST s a Source #

Allow the result of a state transformer computation to be used (lazily) inside the computation.

Note that if f is strict, fixST f = _|_.

liftST :: ST s a -> State# s -> STret s a Source #

liftST is useful when we want a lifted result from an ST computation. See fixST below.

runST :: (forall s. ST s a) -> a Source #

Return the value computed by a state transformer computation. The forall ensures that the internal state used by the ST computation is inaccessible to the rest of the program.

data STRef s a Source #

A value of type STRef s a is a mutable variable in state thread s, containing a value of type a

Constructors

STRef (MutVar# s a) 
Instances
Eq (STRef s a) Source # 
Instance details

Defined in Control.Monad.ST2

Methods

(==) :: STRef s a -> STRef s a -> Bool #

(/=) :: STRef s a -> STRef s a -> Bool #

newSTRef :: a -> ST s (STRef s a) Source #

Build a new STRef in the current state thread

readSTRef :: STRef s a -> ST s a Source #

Read the value of an STRef

writeSTRef :: STRef s a -> a -> ST s () Source #

Write a new value into an STRef

type (∩) s s' = Common s s' Source #

A pretty type alias for Common.

data Common s s' Source #

A type that shows that the state threads s and s' refer to a heap region that overlaps in some way such that s and s' can both access the overlap, while maintaining privacy in their own heap regions.

share :: STRef s a -> ST s (STRef (Common s s') a) Source #

Move a variable that you own into a region with common overlap.

liftL :: ST s a -> ST (Common s s') a Source #

Lift an ST computation into a context with another heap region

liftR :: ST s' a -> ST (Common s s') a Source #

Lift an ST computation into a context with another heap region

use :: STRef (Common s s') a -> STRef s a Source #

Given proof that one has access to the heap regions s and s', yield an STRef to the region s.

symm :: STRef (Common s s') a -> STRef (Common s' s) a Source #

Given proof that one has access to the heap regions s and s', yield an STRef that swaps the order of the regions.

runST2 :: (forall s s'. ST (Common s s') a) -> a Source #

Return the value computed by a state transformer computation over a shared heap. The forall ensures that the internal state(s) used by the ST computation is inaccessible to the rest of the program.

Unsafe API

toBaseST :: ST s a -> ST s a Source #

Convert an ST2 to an ST

fromBaseST :: ST s a -> ST s a Source #

Convert an ST to an ST2

data STret s a Source #

A simple product type containing both the state thread and value inside of the ST

unsafeInterleaveST :: ST s a -> ST s a Source #

unsafeInterleaveST allows an ST computation to be deferred lazily. When passed a value of type ST a, the ST computation will only be performed when the value of the a is demanded.

unsafeDupableInterleaveST :: ST s a -> ST s a Source #

unsafeDupableInterleaveST allows an ST computation to be deferred lazily. When passed a value of type ST a, the ST computation will only be performed when the value of the a is demanded.

The computation may be performed multiple times by different threads, possibly at the same time. To prevent this, use unsafeInterleaveST instead.

stToPrim :: PrimMonad m => ST (PrimState m) a -> m a Source #

Convert an ST action to a PrimMonad.

unsafePrimToST :: PrimBase m => m a -> ST s a Source #

Convert any PrimBase to ST with an arbitrary state token. This operation is highly unsafe!

unsafeSTToPrim :: PrimBase m => ST s a -> m a Source #

Convert an ST action with an arbitrary state token to any PrimMonad. This operation is highly unsafe!

unsafeInlineST :: ST s a -> a Source #

Extract the value out of the ST computation. Compare this to runST; in this case, the rest of the program is permitted to reference the state thread s. This operation is highly unsafe!

stToIO :: ST RealWorld a -> IO a Source #

Embed a strict state transformer in an IO action. The RealWorld parameter indicates that the internal state used by the ST computation is a special one supplied by the IO monad, and thus distinct from those used by invocations of runST.

ioToST :: IO a -> ST RealWorld a Source #

Convert an IO action into an ST action. The type of the result is constrained to use a RealWorld state, and therefore the result cannot be passed to runST.

data RealWorld #

RealWorld is deeply magical. It is primitive, but it is not unlifted (hence ptrArg). We never manipulate values of type RealWorld; it's only used in the type system, to parameterise State#.