ST monads in Hugs
Ross Paterson
ross@soi.city.ac.uk
Fri, 9 May 2003 12:03:00 +0100
I propose to change the internal representation of the strict ST monad to
newtype ST s a = ST (forall r. (a -> r) -> r)
which is a generalization of the new representation of IO monad:
newtype IO a = IO ((a -> IOResult) -> IOResult)
This will enable simple conversion between the monads:
runST :: (forall s. ST s a) -> a
runST m = let ST f = m in f id
stToIO :: ST RealWorld a -> IO a
stToIO (ST f) = IO f
and will allow us to reuse several IO primitives as ST primitives, e.g.
primitive thenStrictST "primbindIO"
:: ST s a -> (a -> ST s b) -> ST s b
primitive returnST "primretIO" :: a -> ST s a
primitive newSTRef "newRef" :: a -> ST s (STRef s a)
primitive primNewArr "IONewArr"
:: (a,a) -> Int -> b -> ST s (STArray s a b)
dispensing with stmonad.c.
For the lazy ST monad, I plan to use
newtype ST s a = ST (State s -> (a, State s))
type State s = ()
lazyToStrictST :: ST s a -> ST.ST s a
lazyToStrictST (ST m) = ST.ST (\k -> case m () of (a,()) -> k a)
strictToLazyST :: ST.ST s a -> ST s a
strictToLazyST (ST.ST m) = ST (\() -> m delay)
where
delay :: a -> (a, State s)
delay a = (a,())
and use the fptools library code, which uses these to lift all the
operations from the strict monad. Then Hugs will have the same interface
to these monads as GHC, with more flexible control over laziness than
before.