X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=Control%2FMonad%2FST%2FLazy.hs;h=5bf12650cd46ae205074efaa9e758538c4ff8821;hb=6b1a36a595eddf1e124529646afdb75c76a9966d;hp=5144dcc8cdab45873ee44bd7f17f61df42d6f0c0;hpb=5545727d5a6a1fc6d5d00f32a92a8fdf0fb7ca77;p=haskell-directory.git diff --git a/Control/Monad/ST/Lazy.hs b/Control/Monad/ST/Lazy.hs index 5144dcc..5bf1265 100644 --- a/Control/Monad/ST/Lazy.hs +++ b/Control/Monad/ST/Lazy.hs @@ -1,86 +1,72 @@ ----------------------------------------------------------------------------- --- +-- | -- Module : Control.Monad.ST.Lazy -- Copyright : (c) The University of Glasgow 2001 --- License : BSD-style (see the file libraries/core/LICENSE) +-- License : BSD-style (see the file libraries/base/LICENSE) -- -- Maintainer : libraries@haskell.org -- Stability : provisional -- Portability : non-portable (requires universal quantification for runST) -- --- $Id: Lazy.hs,v 1.2 2001/07/03 11:37:49 simonmar Exp $ --- --- This module presents an identical interface to Control.Monad.ST, --- but the underlying implementation of the state thread is lazy. +-- This module presents an identical interface to "Control.Monad.ST", +-- 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, - unsafeInterleaveST, fixST, - STRef.STRef, - newSTRef, readSTRef, writeSTRef, - - STArray.STArray, - newSTArray, readSTArray, writeSTArray, boundsSTArray, - thawSTArray, freezeSTArray, unsafeFreezeSTArray, -#ifdef __GLASGOW_HASKELL__ --- no 'good' reason, just doesn't support it right now. - unsafeThawSTArray, -#endif + -- * Converting between strict and lazy 'ST' + strictToLazyST, lazyToStrictST, - ST.unsafeIOToST, ST.stToIO, + -- * Converting 'ST' To 'IO' + RealWorld, + stToIO, - strictToLazyST, lazyToStrictST + -- * Unsafe operations + unsafeInterleaveST, + unsafeIOToST ) where import Prelude -import qualified Data.STRef as STRef -import Data.Array +import Control.Monad.Fix -#ifdef __GLASGOW_HASKELL__ +import Control.Monad.ST (RealWorld) import qualified Control.Monad.ST as ST -import qualified GHC.Arr as STArray + +#ifdef __GLASGOW_HASKELL__ import qualified GHC.ST -import GHC.Base ( ($), ()(..) ) +import GHC.Base import Control.Monad -import Data.Ix -import GHC.Prim #endif #ifdef __HUGS__ -import qualified ST -import Monad -import Ix -import Array -import PrelPrim ( unST - , mkST - , PrimMutableArray - , PrimArray - , primNewArray - , primReadArray - , primWriteArray - , primUnsafeFreezeArray - , primSizeMutableArray - , primSizeArray - , primIndexArray - ) +import Hugs.LazyST #endif - #ifdef __GLASGOW_HASKELL__ +-- | The lazy 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 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) -#endif - -#ifdef __HUGS__ -newtype ST s a = ST (s -> (a,s)) -#endif instance Functor (ST s) where fmap f m = ST $ \ s -> @@ -104,116 +90,37 @@ instance Monad (ST s) where in k_a new_s - -#ifdef __GLASGOW_HASKELL__ {-# NOINLINE runST #-} +-- | 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. runST :: (forall s. ST s a) -> a runST st = case st of ST the_st -> let (r,_) = the_st (S# realWorld#) in r -#endif - -#ifdef __HUGS__ -runST :: (__forall s. ST s a) -> a -runST st = case st of ST the_st -> let (r,_) = the_st realWorld in r - where realWorld = error "runST: entered the RealWorld" -#endif +-- | Allow the result of a state transformer computation to be used (lazily) +-- inside the computation. +-- 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 + (r,s') = m_r s in - (r,s)) - --- --------------------------------------------------------------------------- --- Variables - -newSTRef :: a -> ST s (STRef.STRef s a) -readSTRef :: STRef.STRef s a -> ST s a -writeSTRef :: STRef.STRef s a -> a -> ST s () - -newSTRef = strictToLazyST . STRef.newSTRef -readSTRef = strictToLazyST . STRef.readSTRef -writeSTRef r a = strictToLazyST (STRef.writeSTRef r a) - --- -------------------------------------------------------------------------- --- Arrays - -newSTArray :: Ix ix => (ix,ix) -> elt -> ST s (STArray.STArray s ix elt) -readSTArray :: Ix ix => STArray.STArray s ix elt -> ix -> ST s elt -writeSTArray :: Ix ix => STArray.STArray s ix elt -> ix -> elt -> ST s () -boundsSTArray :: Ix ix => STArray.STArray s ix elt -> (ix, ix) -thawSTArray :: Ix ix => Array ix elt -> ST s (STArray.STArray s ix elt) -freezeSTArray :: Ix ix => STArray.STArray s ix elt -> ST s (Array ix elt) -unsafeFreezeSTArray :: Ix ix => STArray.STArray s ix elt -> ST s (Array ix elt) - -#ifdef __GLASGOW_HASKELL__ - -newSTArray ixs init = strictToLazyST (STArray.newSTArray ixs init) - -readSTArray arr ix = strictToLazyST (STArray.readSTArray arr ix) -writeSTArray arr ix v = strictToLazyST (STArray.writeSTArray arr ix v) -boundsSTArray arr = STArray.boundsSTArray arr -thawSTArray arr = strictToLazyST (STArray.thawSTArray arr) -freezeSTArray arr = strictToLazyST (STArray.freezeSTArray arr) -unsafeFreezeSTArray arr = strictToLazyST (STArray.unsafeFreezeSTArray arr) -unsafeThawSTArray arr = strictToLazyST (STArray.unsafeThawSTArray arr) + (r,s')) #endif - -#ifdef __HUGS__ -newSTArray ixs elt = do - { arr <- strictToLazyST (primNewArray (rangeSize ixs) elt) - ; return (STArray ixs arr) - } - -boundsSTArray (STArray ixs arr) = ixs -readSTArray (STArray ixs arr) ix - = strictToLazyST (primReadArray arr (index ixs ix)) -writeSTArray (STArray ixs arr) ix elt - = strictToLazyST (primWriteArray arr (index ixs ix) elt) -freezeSTArray (STArray ixs arr) = do - { arr' <- strictToLazyST (primFreezeArray arr) - ; return (Array ixs arr') - } - -unsafeFreezeSTArray (STArray ixs arr) = do - { arr' <- strictToLazyST (primUnsafeFreezeArray arr) - ; return (Array ixs arr') - } - -thawSTArray (Array ixs arr) = do - { arr' <- strictToLazyST (primThawArray arr) - ; return (STArray ixs arr') - } - -primFreezeArray :: PrimMutableArray s a -> ST.ST s (PrimArray a) -primFreezeArray arr = do - { let n = primSizeMutableArray arr - ; arr' <- primNewArray n arrEleBottom - ; mapM_ (copy arr arr') [0..n-1] - ; primUnsafeFreezeArray arr' - } - where - copy arr arr' i = do { x <- primReadArray arr i; primWriteArray arr' i x } - arrEleBottom = error "primFreezeArray: panic" - -primThawArray :: PrimArray a -> ST.ST s (PrimMutableArray s a) -primThawArray arr = do - { let n = primSizeArray arr - ; arr' <- primNewArray n arrEleBottom - ; mapM_ (copy arr arr') [0..n-1] - ; return arr' - } - where - copy arr arr' i = primWriteArray arr' i (primIndexArray arr i) - arrEleBottom = error "primFreezeArray: panic" -#endif +instance MonadFix (ST s) where + mfix = fixST -- --------------------------------------------------------------------------- -- Strict <--> Lazy #ifdef __GLASGOW_HASKELL__ +{-| +Convert a strict 'ST' computation into a lazy one. The strict state +thread passed to 'strictToLazyST' is not performed until the result of +the lazy state thread it returns is demanded. +-} strictToLazyST :: ST.ST s a -> ST s a strictToLazyST m = ST $ \s -> let @@ -223,25 +130,23 @@ strictToLazyST m = ST $ \s -> in (r, s') +{-| +Convert a lazy 'ST' computation into a strict one. +-} lazyToStrictST :: ST s a -> ST.ST s a lazyToStrictST (ST m) = GHC.ST.ST $ \s -> case (m (S# s)) of (a, S# s') -> (# s', a #) -#endif - -#ifdef __HUGS__ -strictToLazyST :: ST.ST s a -> ST s a -strictToLazyST m = ST $ \s -> - let - pr = unST m s - r = fst pr - s' = snd pr - in - (r, s') - - -lazyToStrictST :: ST s a -> ST.ST s a -lazyToStrictST (ST m) = mkST $ m -#endif unsafeInterleaveST :: ST s a -> ST s a unsafeInterleaveST = strictToLazyST . ST.unsafeInterleaveST . lazyToStrictST +#endif + +unsafeIOToST :: IO a -> ST s a +unsafeIOToST = strictToLazyST . ST.unsafeIOToST + +-- | A monad transformer embedding lazy state transformers in the 'IO' +-- 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