PureScript "inner" 量化类型

PureScript "inner" quantified type

我假设我在图块中的术语有误 - 让我知道我应该在下面使用什么来代替。

PureScript by Example, section 8.17 Mutable State中有讨论runST的类型:

runST :: forall a eff. (forall h. Eff (st :: ST h | eff) a) -> Eff eff a

The thing to notice here is that the region type h is quantified inside the parentheses on the left of the function arrow. That means that whatever action we pass to runST has to work with any region h whatsoever.

我理解最终目标,但是有人可以从类型的角度阐明这个陈述,以及如何按照上述限制吗?

如果可能,是否可以在更简单的类型上显示差异,例如有什么区别:

f1 :: forall i o. Array i -> Array o
f2 :: forall o. (forall i. Array i) -> Array o

我认为一个简短的例子会有所帮助。

类型 Array a 包含哪些值?

好吧,如果您知道 a 是什么,或者了解 a,那么您也许可以举出具体的例子。如果已知 aInt,那么 [1, 2, 3] 是一个很好的答案。如果 a 有一个 Monoid 实例,那么 [mempty] 有效。但是,如果您对 a 一无所知,那么您唯一可以自信地给出的答案是 [].

类型 forall a. Array a 包含哪些值?

对于 a 的任何选择,任何属于该类型的值都必须属于 Array a。由于我们对a一无所知,答案又是"only []"。所以在这种情况下,forall 将我们限制为只有一种可能的类型实现。

现在 forall a. Array a 是一个和其他类型一样的类型,所以它可以作为函数的参数类型出现。作为此类函数的调用者,您只能提供一个可能的值。作为该函数的 实现者 ,您可以选择使用具有 any 类型 a 的参数(因为它必须适用于任何类型你选择)。

runST也是如此。 runST 的实现者可以选择使用它喜欢的任何 h 来调用您的操作,因此它(概念上)会生成一个新的内存区域供您使用。作为调用者,您必须使用给定的任何内存区域,而无需对此一无所知。这意味着您只能抽象地使用提供的操作(newSTRefwriteSTRef 等),并且您创建的任何引用都不能离开 runST 块的范围(类型变量 h 不存在于该范围之外,毕竟),这允许 runST 到 return 一个安全的纯结果。

因此,forall 是一个有用的工具,用于限制可以作为函数参数提供的值。