Add blockST for nested ST scopes
GHC lacks the blockST
and importVar
primitives introduced by Launchbury/Sabry:
- http://www.cs.indiana.edu/\~sabry/papers/monadic-state-ax.pdf (section 10).
- See also Fluet & Morrisset http://www.cs.rit.edu/\~mtf/research/rgn-monad/JFP06/jfp06.pdf (page 7ff)
The two new combinators have these types:
blockST :: (forall r. ST (s,r) a) -> ST s a
importVar :: STRef s a -> STRef (s,r) a
They are useful, and have no runtime cost; I don't think it'd be hard to provide them. We need these primitives, I think:
promoteState# :: State# s -> State# (s,r) a
demoteState# :: State# (s,r) -> State# s
promoteVar# :: MutVar# s a -> MutVar# (s,r) a
All three are implemented as no-ops. (Compare with newMutVar#
etc in http://darcs.haskell.org/ghc/compiler/prelude/primops.txt.pp.)
Now the implementations look (something) like this. (For background see the current impementations of ST
and STRef
in http://darcs.haskell.org/packages/base/GHC (ST.lhs
and STRef.lhs
resp.)
blockST (ST thing) = ST (\s -> case thing (promoteState# s) of
(s', r) -> (demoteState# s', r) )
promoteVar (STRef r) = STRef (promoteVar# r)
Things to think about:
- Can we use coercions instead of primops? (I think yes for
promote/demoteState
but it's unsound to demote variables.) - I'm hazy about what type safety guarantees we still have in Core, where the representation of the state monad is exposed.
- Nomenclature. I'm not attached to these particular names.
- Is there other relevant background material?