Search code examples
haskellstate-monad

Is this generalization of runST safe?


Control.Monad.ST in the base package contains runST to run the strict state-transformer monad:

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

However, I need a generalized version of runST:

runSTCont :: (forall s . (forall b . ST s b -> b) -> a) -> a
runSTCont f = f $ \m -> runST $ unsafeCoerce m

My question is: Is this use of unsafeCoerse safe? (I guess so, because as I understand, the only purpose of the index s is to prevent to leak s-indexed values in the result a. The type of runSTCont cannot leak s-indexed values so it should be OK.)

Note that runST can be expressed in terms of runSTCont so runSTCont is at least as general as runST:

runST' :: (forall s. ST s a) -> a 
runST' m = runSTCont $ \runST -> runST m

Solution

  • I don't think so:

    crash = runSTCont crasher where
      crasher :: forall s. (forall b . ST s b -> b) -> Integer
      crasher go =
        let r :: forall a. STRef s (a -> a)
            r = go $ newSTRef id
        in go $ do writeSTRef r (tail . tail)
                   f <- readSTRef r
                   return $ f (17 :: Integer)
    

    The problem is that Haskell lacks the value restriction.