X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Control%2FMonad%2FST%2FLazy.hs;h=8aac6651a7c95de5eeef3a907582a6daf073853c;hb=41e8fba828acbae1751628af50849f5352b27873;hp=b91e062604ea70b682729519757bc61ca8204936;hpb=413f1d5a1537ec712423f84003cc30fbfe399f11;p=ghc-base.git diff --git a/Control/Monad/ST/Lazy.hs b/Control/Monad/ST/Lazy.hs index b91e062..8aac665 100644 --- a/Control/Monad/ST/Lazy.hs +++ b/Control/Monad/ST/Lazy.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE CPP, MagicHash, UnboxedTuples, Rank2Types #-} + ----------------------------------------------------------------------------- -- | -- Module : Control.Monad.ST.Lazy @@ -9,40 +11,38 @@ -- Portability : non-portable (requires universal quantification for runST) -- -- This module presents an identical interface to "Control.Monad.ST", --- but the underlying implementation of the state thread is /lazy/ (in --- the sense that (@_|_ >> a@ is not necessarily equal to @_|_@). +-- except that the monad delays evaluation of state operations until +-- a value depending on them is required. -- ----------------------------------------------------------------------------- module Control.Monad.ST.Lazy ( - -- * The 'ST' monad - ST, - runST, - fixST, + -- * The 'ST' monad + ST, + runST, + fixST, - -- * Converting between strict and lazy 'ST' - strictToLazyST, lazyToStrictST, + -- * Converting between strict and lazy 'ST' + strictToLazyST, lazyToStrictST, - -- * Converting 'ST' To 'IO' - RealWorld, - stToIO, + -- * Converting 'ST' To 'IO' + RealWorld, + stToIO, - -- * Unsafe operations - unsafeInterleaveST, - unsafeIOToST + -- * Unsafe operations + unsafeInterleaveST, + unsafeIOToST ) where import Prelude import Control.Monad.Fix -import Control.Monad.ST (RealWorld) import qualified Control.Monad.ST as ST #ifdef __GLASGOW_HASKELL__ import qualified GHC.ST import GHC.Base -import Control.Monad #endif #ifdef __HUGS__ @@ -51,10 +51,20 @@ import Hugs.LazyST #ifdef __GLASGOW_HASKELL__ -- | The lazy state-transformer monad. --- The first parameter is used solely to keep the states of different --- invocations of 'runST' separate from each other and from invocations --- of 'Control.Monad.ST.stToIO'. In the first case the type parameter --- is not instantiated; in the second it is 'RealWorld'. +-- 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 unstantiated 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 not strict in the state. For example, +-- +-- @'runST' (writeSTRef _|_ v >>= readSTRef _|_ >> return 2) = 2@ newtype ST s a = ST (State s -> (a, State s)) data State s = S# (State# s) @@ -70,7 +80,7 @@ instance Monad (ST s) where return a = ST $ \ s -> (a,s) m >> k = m >>= \ _ -> k - fail s = error s + fail s = error s (ST m) >>= k = ST $ \ s -> @@ -82,25 +92,25 @@ instance Monad (ST s) where {-# NOINLINE runST #-} -- | Return the value computed by a state transformer computation. --- The @forall@ is a technical device to ensure that the state used --- by the 'ST' computation is inaccessible to the rest of the program. +-- The @forall@ ensures that the internal state used by the 'ST' +-- computation is inaccessible to the rest of the program. runST :: (forall s. ST s a) -> a runST st = case st of ST the_st -> let (r,_) = the_st (S# realWorld#) in r -- | Allow the result of a state transformer computation to be used (lazily) -- inside the computation. --- Note that if @f@ is strict, @'fixST' f@ will diverge. +-- Note that if @f@ is strict, @'fixST' f = _|_@. fixST :: (a -> ST s a) -> ST s a fixST m = ST (\ s -> - let - ST m_r = m r - (r,s') = m_r s - in - (r,s')) + let + ST m_r = m r + (r,s') = m_r s + in + (r,s')) #endif instance MonadFix (ST s) where - mfix = fixST + mfix = fixST -- --------------------------------------------------------------------------- -- Strict <--> Lazy @@ -114,11 +124,11 @@ the lazy state thread it returns is demanded. strictToLazyST :: ST.ST s a -> ST s a strictToLazyST m = ST $ \s -> let - pr = case s of { S# s# -> GHC.ST.liftST m s# } - r = case pr of { GHC.ST.STret _ v -> v } - s' = case pr of { GHC.ST.STret s2# _ -> S# s2# } - in - (r, s') + pr = case s of { S# s# -> GHC.ST.liftST m s# } + r = case pr of { GHC.ST.STret _ v -> v } + s' = case pr of { GHC.ST.STret s2# _ -> S# s2# } + in + (r, s') {-| Convert a lazy 'ST' computation into a strict one. @@ -135,7 +145,8 @@ unsafeIOToST :: IO a -> ST s a unsafeIOToST = strictToLazyST . ST.unsafeIOToST -- | A monad transformer embedding lazy state transformers in the 'IO' --- monad. The 'RealWorld' parameter is a technical device to keep the --- state used by such computations separate from those inside 'runST'. +-- monad. 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'. stToIO :: ST RealWorld a -> IO a stToIO = ST.stToIO . lazyToStrictST