# Merging ST threads

### From HaskellWiki

Revision as of 01:12, 8 October 2006 by DonStewart (Talk | contribs)

In the thread starting at http://www.haskell.org//pipermail/haskell/2004-January/013330.html there is a discussion about temporarily combining two independent monadic state threads. The problem is this: we have a computation that works with one bit of state, say a , and another that
works with another bit of state, say an , and we want to make one that works with both the and the simultaneously for a while, and then go back to computations working on them individually.
So what we want is, given and computations that work with the and the respectively, an computation that works with the pair , and then computations and that work with the individual states, to construct the combined computation that does and , then , then and .
This removes the asymmetry, but isn't really any nicer otherwise. However, what would be neat is if we could do this with ST threads too. ST is the extension present in at least GHC and Hugs that has an imperative implementation, and makes clever use of a in a type to guarantee purity.
Which guarantees that state variables ( etc) cannot "escape" from one state thread to another.
Of course, we won't be able to run values of type , since they violate the . So we need some way to get rid of the tuple:

Bool

Int

Bool

Int

start1

start2

Bool

Int

intermediate

(Bool,Int)

end1

end2

start1

start2

intermediate

end1

end2

One solution is to define the individual computations using the StateT monad transformer, and then stack the two monad transformers on top of each other to make the combined one. This is a bit nasty and asymmetric, requiring one computation to be "lifted":

whole = do start1 lift start2 intermediate end1 lift end2

Another option is to work with the normal State monad, and to define operations on this monad that "lifts" the state into a tuple:

embedState1 :: State s a -> State (s,t) a embedState2 :: State t a -> State (s,t) a embedState1 (State f) = State (\(s,t) -> let (s',a)=f s in ((s',t),a)) embedState2 (State f) = State (\(s,t) -> let (t',a)=f s in ((s,t'),a)) whole = do embedState1 start1 embedState2 start2 intermediate embedState1 end1 embedState2 end2

forall

The key point is the operation

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

STRef

If we want to do the above with then ST, then we probably want operations like this:

embedST1 :: ST s a -> ST (s,t) a embedST2 :: ST t a -> ST (s,t) a

ST (s,t) a

forall}}} restriction on <hask>runST

finishST1 :: (forall s . ST (s,t) a) -> ST t a finishST2 :: (forall t . ST (s,t) a) -> ST s a

Does this make sense? Is it safe? I doubt it's very useful, but I think it's probably implementable with a bit of hacking inside the implementation of ST.

-- GaneshSittampalam