Control.Monad.ST
包中的 base
包含runST
来运行严格的状态变换器monad:
runST :: (forall s. ST s a) -> a
但是,我需要runST
的广义版本:
runSTCont :: (forall s . (forall b . ST s b -> b) -> a) -> a
runSTCont f = f $ \m -> runST $ unsafeCoerce m
我的问题是:unsafeCoerse
使用安全吗?
(我想是的,因为据我了解,索引s
的唯一目的是防止s
- 在结果a
中泄露runSTCont
- 索引值。{{1}的类型}不能泄漏s
- 索引值,所以它应该没问题。)
请注意,runST
可以用runSTCont
表示,因此runSTCont
至少与runST
一样通用:
runST' :: (forall s. ST s a) -> a
runST' m = runSTCont $ \runST -> runST m
答案 0 :(得分: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)
问题在于Haskell缺乏价值限制。