Opened 7 years ago

Last modified 22 months ago

#5073 new feature request

Add blockST for nested ST scopes

Reported by: simonpj Owned by:
Priority: low Milestone:
Component: Compiler Version: 7.0.3
Keywords: Cc: wadler@…, Matthew.Fluet@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:

Description (last modified by simonpj)

GHC lacks the blockST and importVar primitives introduced by Launchbury/Sabry:

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

Now the implementations look (something) like this. (For background see the current impementations of ST and STRef in (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?

Change History (13)

comment:1 Changed 7 years ago by simonpj

Description: modified (diff)

comment:2 Changed 7 years ago by wadler

Cc: wadler@… added

comment:3 Changed 7 years ago by matthew.fluet

Cc: Matthew.Fluet@… added

comment:4 Changed 7 years ago by matthew.fluet

It does seem simple enough to add. And I think it is a good building block (pun?) for other, more sophisticated scope handling mechanisms, along the lines that John alluded to.

However, it does seem that it is more useful to move *computations* from one ST scope to another. That is, as mentioned in the Region Monad paper by way of Simon, making the two primitives be:

  blockST :: (forall r. ST (s,r) a) -> ST s a
  importST :: ST s a -> ST (s, r) a

importVar requires that you have your hands on all of the STRef-s, which makes it hard to abstract over computations. importST seems to simply be the public face of the proposed promoteState# primitive. (Is there a typo in the type of promoteState#? The final a seems out of place.)

comment:5 Changed 7 years ago by simonpj

Ah yes, your importST is much better. Yes, the type of promoteState# has a bogus a. Thanks.

comment:6 Changed 6 years ago by igloo

Milestone: 7.4.1

comment:7 Changed 6 years ago by igloo

Priority: normallow

comment:8 Changed 5 years ago by igloo


comment:9 Changed 3 years ago by thoughtpolice


Moving to 7.10.1.

comment:10 Changed 3 years ago by thomie

difficulty: Unknown
Type: bugfeature request

comment:11 Changed 3 years ago by thoughtpolice


Moving to 7.12.1 milestone; if you feel this is an error and should be addressed sooner, please move it back to the 7.10.1 milestone.

comment:12 Changed 2 years ago by thoughtpolice


Milestone renamed

comment:13 Changed 22 months ago by thomie

Milestone: 8.0.1
Note: See TracTickets for help on using tickets.