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.