这种runST的推广是否安全?

Pét*_*zky 9 haskell state-monad

Control.Monad.STbase包中包含runST运行严格的状态变换器monad:

runST :: (forall s. ST s a) -> a
Run Code Online (Sandbox Code Playgroud)

但是,我需要一个通用版本runST:

runSTCont :: (forall s . (forall b . ST s b -> b) -> a) -> a
runSTCont f = f $ \m -> runST $ unsafeCoerce m
Run Code Online (Sandbox Code Playgroud)

我的问题是:这是否unsafeCoerse安全使用?(我想是的,因为据我所知,索引的唯一目的s是防止s在结果中泄漏索引值a.runSTCont不能泄漏s索引值的类型,所以应该没问题.)

请注意,runST在来表示runSTCont这样runSTCont至少一般为runST:

runST' :: (forall s. ST s a) -> a 
runST' m = runSTCont $ \runST -> runST m
Run Code Online (Sandbox Code Playgroud)

Phi*_* JF 12

我不这么认为:

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)
Run Code Online (Sandbox Code Playgroud)

问题是Haskell缺乏价值限制.

  • 我希望能更好地理解这个答案.有没有办法改变提供的类型,使其安全.似乎当前的一个接近允许,但它泄漏了对"unsafeCoerce"的访问权限.如果您可以访问ST构造函数,是否可以更好地实现此功能? (2认同)