gpt4 book ai didi

haskell - ST monad 是如何工作的?

转载 作者:行者123 更新时间:2023-12-02 11:38:51 26 4
gpt4 key购买 nike

据我了解,ST monad 有点像 IO 的弟弟,而 IO 又是添加了 RealWorld 魔力的状态 monad。我可以想象状态,也可以想象 RealWorld 以某种方式放入 IO 中,但每次我编写 ST 的类型签名时,ST monad 的 s 都会让我感到困惑。

ST s (STArray s a b)为例。 s 在那里如何工作?它是否只是用于在计算之间建立一些人工数据依赖关系,而不能像状态单子(monad)中的状态一样被引用(由于forall)?

我只是抛出一些想法,非常感谢比我更有知识的人向我解释它。

最佳答案

s将对象保留在 ST 内monad 泄露到外部 ST单子(monad)。

-- This is an error... but let's pretend for a moment...
let a = runST $ newSTRef (15 :: Int)
b = runST $ writeSTRef a 20
c = runST $ readSTRef a
in b `seq` c

好吧,这是一个类型错误(这是一件好事!我们不希望 STRef 泄漏到原始计算之外!)。这是一个类型错误,因为额外的 s 。请记住runST有签名:

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

这意味着s您正在运行的计算必须没有任何限制。因此,当您尝试评估a时:

a = runST (newSTRef (15 :: Int) :: forall s. ST s (STRef s Int))

结果的类型为 STRef s Int ,这是错误的,因为 s已“逃出” forall 之外在runST 。类型变量始终必须出现在 forall 的内部。 ,并且 Haskell 允许隐式 forall量词无处不在。根本没有任何规则可以让您有意义地找出 a 的返回类型。 .

另一个例子 forall :清楚地表明为什么你不能让事情逃脱 forall ,这是一个更简单的示例:

f :: (forall a. [a] -> b) -> Bool -> b
f g flag =
if flag
then g "abcd"
else g [1,2]

> :t f length
f length :: Bool -> Int

> :t f id
-- error --

当然f id是一个错误,因为它将返回 Char 的列表或 Int 的列表取决于 bool 值是真还是假。这是完全错误的,就像 ST 的例子一样.

另一方面,如果您没有 s输入参数,然后所有内容都会进行类型检查,即使代码显然是伪造的。

ST 实际工作原理:在实现方面,ST monad 实际上与 IO 相同monad 但界面略有不同。当您使用ST时你实际上得到了 monad unsafePerformIO或同等的,在幕后。您可以安全地执行此操作的原因是因为所有 ST 的类型签名相关功能,特别是带有 forall 的部分.

关于haskell - ST monad 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12468622/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com