我认为我在瓷砖中的术语是错误的 - 让我知道我应该使用什么代替以下。
在PureScript by Example, section 8.17 Mutable State中,我们讨论了runST
的类型:
runST :: forall a eff. (forall h. Eff (st :: ST h | eff) a) -> Eff eff a
这里要注意的是,区域类型h在功能箭头左侧的括号内量化。这意味着我们传递给runST的任何操作都必须与任何区域一起工作。
我理解最终目标,但有人可以从类型的角度澄清这个陈述,以及如何限制它如上所述?
如果可能,可以在更简单的类型上显示差异,例如有什么区别:
f1 :: forall i o. Array i -> Array o
f2 :: forall o. (forall i. Array i) -> Array o
我认为一个简短的例子会有所帮助。
答案 0 :(得分:1)
类型Array a
中包含哪些值?
好吧,如果您知道a
是什么,或者a
,那么您可以提供具体的例子。如果知道a
为Int
,那么[1, 2, 3]
就是一个很好的答案。如果a
有Monoid
个实例,则[mempty]
有效。但是,如果您对a
一无所知,那么您可以自信地回答的唯一答案是[]
。
类型forall a. Array a
中包含哪些值?
对于Array a
的任何选择,任何居住在该类型中的值都必须居住a
。由于我们对a
一无所知,答案是#34;只有[]
"再次。因此,在这种情况下,forall
将我们限制为只有一种类型的可能实现。
现在forall a. Array a
类似于任何其他类型,因此它可以显示为函数的参数类型。作为此类函数的调用者,您只能提供一个可能的值。作为该函数的实现者,您可以选择将参数与任何类型a
一起使用(因为它必须适用于您选择的任何类型)。
runST
也是如此。 runST
的实施者可以选择使用任何h
来调用您的操作,因此它(从概念上)会生成一个新的内存区域供您使用。作为调用者,您必须处理所给予的任何内存区域,而不了解它。这意味着您只能抽象地使用提供的操作(newSTRef
,writeSTRef
等),并且您创建的任何引用都不能离开runST
块的范围(类型变量{毕竟,{1}}不存在于该范围之外,这允许h
安全地返回纯结果。
因此,runST
是一个有用的工具,用于限制可以作为函数参数提供的值。