Haskell 这是runST的推广吗?
Haskell 这是runST的推广吗?,haskell,state-monad,Haskell,State Monad,base包中的Control.Monad.ST包含运行严格状态转换器Monad的runST: 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 runST' :: (forall s. ST s
base
包中的Control.Monad.ST
包含运行严格状态转换器Monad的runST
:
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
runST' :: (forall s. ST s a) -> a
runST' m = runSTCont $ \runST -> runST m
我的问题是:这种使用unsafectorse
安全吗?
(我想是这样,因为据我所知,索引s
的唯一目的是防止在结果a
中泄漏s
-索引值。runSTCont
的类型不能泄漏s
-索引值,所以应该可以。)
请注意,runST
可以用runSTCont
表示,因此runSTCont
至少与runST
一样通用:
runSTCont :: (forall s . (forall b . ST s b -> b) -> a) -> a
runSTCont f = f $ \m -> runST $ unsafeCoerce m
runST' :: (forall s. ST s a) -> a
runST' m = runSTCont $ \runST -> runST m
我不这么认为:
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)
crash=runSTCont crasher在哪里
克拉舍:福尔斯。(对于所有b.ST s b->b)->整数
冲锋枪=
让r::对于所有a。应力s(a->a)
r=go$newSTRef id
in-go$do-writeSTRef r(tail.tail)
f您是否可以添加一个用例,为什么需要ruNSTCont
?@PetrPudlák,我有一个复杂的用例。我想我可以简化它,但最简单的用例是runSTCont
本身的实现。我想避免类似“这个用例也可以用runST实现”这样的评论。这是这个特定的runSTCont
实现的问题,还是它的一般类型的问题?@PetrPudlák这是一个一般类型的问题。如果Haskell是按名称调用的,那就好了,但是因为它是按需调用实现的,所以你不能泛化effectfull表达式——即使效果(即,你修改的heaplet)被限制在一个“模块”中,而这正是runSTCont
所做的。我很想更好地理解这个答案。是否有方法更改提供的类型以使其安全。看起来当前版本接近允许版本,但它泄漏了对unsafeccerce
的访问权限。如果您可以访问ST构造函数,这个函数是否可以更好地实现?