ST monad如何工作?


77

我知道ST monad有点像IO的小弟弟,而IO则是带有附加RealWorld魔术的状态monad 。我能想象的状态,我能想象的是现实世界被莫名其妙地投入IO,但每次我写的类型签名STs的ST单子让我困惑的。

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

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


如果您搜索“ ST monad”,那么会有一个条目回答我的问题,作为有关STArrays的问题的补充。不知道我的问题现在是否重复。stackoverflow.com/questions/8197032/…–
大卫

2
简单回答“是”是如此诱人。对你的问题。:)
AndrewC

我猜想添加到问题的链接并将其关闭将使a)将来使搜索变得更容易,并且b)节省一些答案。
David

2
我将为您指出我在rank-2类型上的文章,这也应该有助于您理解STmonad。了解了等级2类型如何控制“谁选择”用于类型变量的类型后,这将有助于您了解ST操作如何使用等级2防止其计算被非法使用。
路易斯·卡西利亚斯

您可以编写a :: ST Int Int; a = return 2 ST一个完全普通的状态monad,不同的是,它使用未装箱对作为状态函数的输出,State# s -> (# State# s, a #)这使它难以处理。runST尽管ST本身不是一个等级,但这个谜团完全属于2级类型。
应用性

Answers:


75

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))

结果将具有type STRef s Int,这是错误的,因为ins已“转义”到forallin之外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是一个错误,因为它将根据布尔值是true还是false返回一个listChar或一个list of Int。这完全是错误的,就像的示例一样ST

另一方面,如果您没有stype参数,那么即使代码显然是伪造的,所有东西都将进行类型检查。

ST的实际工作方式:在实现方面,STmonad实际上与IOmonad相同,但接口略有不同。当您使用STmonad时,您实际上会unsafePerformIO在幕后得到或等效的结果。之所以可以安全地执行此操作,是因为所有ST相关功能的类型签名,尤其是带有forall。的部分。


您可以通过realWorld#直接在客户端代码中进行模仿来“破坏” ST的安全性runSTRep吗?当然,这是一个坏主意,但是我想知道这些保护是什么,除了realworld#在程序中使用显然是不安全的值之外。 hackage.haskell.org/package/base-4.6.0.1/docs/src/...
misterbee

@misterbee是的,它甚至不一定不安全。请记住,s仅存在于类型级别。
PyRulez

28

s只是使类型系统阻止您执行不安全操作的一种手段。它在运行时不“做”任何事情。它只会使类型检查器拒绝执行可疑程序的程序。(这是一种所谓的幻影类型,仅存在于类型检查器的头部,在运行时不受影响的任何事物。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.