ST monad是如何工作的?

我明白,ST monad就像IO的一个小兄弟,反过来也是joinRealWorld魔法的状态monad。 我可以描绘出状态,我可以想象RealWorld是以某种方式投入到IO中的,但是每次我写ST的types签名时,ST monad的s让我困惑。

ST s (STArray sab)为例。 它在那里工作? 它只是用来在计算之间build立一些仿真数据依赖关系,而不能像状态monad中的状态那样引用(由于全部)?

我只是抛出想法,会非常感激比我更懂事的人向我解释。

ST使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 

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

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

这意味着您正在运行的计算上的s必须没有限制。 所以当你尝试评估a

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

结果将会有typesSTRef s Int ,这是错误的,因为srunST之外已经“逃脱”了。 typesvariables总是必须出现在所有的内部,并且Haskell允许隐含的所有量词在任何地方。 没有什么规则可以让你有意义地找出a的返回types。

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

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

当然f id是一个错误,因为它会返回一个Char列表或一个Int列表,这取决于布尔值是true还是false。 这是错误的,就像ST的例子。

另一方面,如果你没有stypes的参数,那么所有stypes都可以检查,即使代码显然是非常不正确的。

ST实际上是如何工作的:实施方面, ST monad实际上与IO monad相同,但是接口略有不同。 当你使用ST monad时,你实际上会在幕后获得unsafePerformIO或者其他等价物。 你可以安全地做这个事情的原因是所有ST相关函数的types签名,尤其是所有与ST相关的函数。

这只是一个黑客,使types系统阻止你做不安全的事情。 它在运行时不会“做”任何事情; 它只是使types检查器拒绝程序做可疑的事情。 (这是一种所谓的幻象types ,只存在于types检查器的头部,并且在运行时不会影响任何东西。)