繁体   English   中英

ST monad是如何工作的?

[英]How does the ST monad work?

我知道ST monad就像是IO的小弟弟,而后者又是添加了RealWorld魔法的状态monad。 我可以想象状态,我可以想象RealWorld以某种方式放入IO,但每次我写ST的类型签名时,ST monad的s让我感到困惑。

ST s (STArray sab)为例。 那里s工作怎么样? 它是否仅用于在计算之间建立一些人为数据依赖性而不能像状态monad中的状态那样被引用(由于forall )?

我只是抛出想法,真的很感谢比我更有知识的人向我解释。

s保持内部的物体ST单子泄露到外面ST单子。

-- 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 ,这是错误的,因为srunST已经“逃逸”在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列表,具体取决于布尔值是true还是false。 这是完全错误的,就像ST的例子一样。

另一方面,如果你没有s类型参数,那么一切都会打字就好了,即使代码显然很伪造。

ST实际上是如何工作的:实现方面, ST monad实际上与IO monad相同,但界面略有不同。 当你使用ST monad时,你实际上得到了unsafePerformIO或等效的幕后。 您可以安全地执行此操作的原因是因为所有ST相关函数的类型签名,尤其是具有forall的部分。

s只是一个黑客,它使类型系统阻止你做一些不安全的事情。 它在运行时没有“做”任何事情; 它只是使类型检查器拒绝执行可疑事情的程序。 (它是一种所谓的幻像类型 ,只存在于类型检查器的头部,并且在运行时不会影响任何内容。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM