# Merging ST threads

### From HaskellWiki

(Difference between revisions)

BrettGiles (Talk | contribs) m (Merging ST Threads moved to Merging ST threads) |
m (typo) |
||

Line 49: | Line 49: | ||

</haskell> |
</haskell> |
||

− | Of course, we won't be able to run values of type <hask>ST (s,t) a</hask>, since they violate the <hask>forall}}} restriction on <hask>runST</hask>. So we need some way to get rid of the tuple: |
+ | Of course, we won't be able to run values of type <hask>ST (s,t) a</hask>, since they violate the <hask>forall</hask> restriction on <hask>runST</hask>. So we need some way to get rid of the tuple: |

<haskell> |
<haskell> |

## Latest revision as of 21:14, 18 May 2007

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 aBool

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

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