我可以理解allowing mutable
是价值限制和弱多态的原因。基本上,函数内部的可变引用可能会改变所涉及的类型并影响函数的未来使用。因此,在类型不匹配的情况下可能不会引入真正的多态性。
例如,
# let remember =
let cache = ref None in
(fun x ->
match !cache with
| Some y -> y
| None -> cache := Some x; x)
;;
val remember : '_a -> '_a = <fun>
请记住,缓存最初是'a option
,但是一旦第一次调用let () = remember 1
,缓存就变为int option
,因此类型变得有限。价值限制解决了这个潜在的问题。
我仍然不明白的是对部分申请的价值限制。
例如,
let identity x = x
val identity: 'a -> 'a = <fun>
let map_rep = List.map identity
val map_rep: '_a list -> '_a list = <fun>
在上面的函数中,我没有看到任何引用或可变的地方,为什么仍然应用值限制?
答案 0 :(得分:3)
这篇文章描述了OCaml目前对价值限制的处理:
它对问题及其历史有很好的总结。
以下是一些观察结果,以及它们的价值。我不是专家,只是业余观察员:
&#34; value&#34;的含义在术语&#34;价值限制&#34;技术性很强,并且与特定语言操纵的值没有直接关系。它是句法术语;也就是说,只需查看程序的符号就可以识别数值,而不需要了解类型。
制作价值限制过于严格的例子并不难。即,当值限制禁止它时,可以安全地推广类型。但是,尝试做得更好(允许更多的概括)会导致规则太难以记住并且仅仅为了凡人(例如我自己)。
在确实安全的时候推广这个障碍不是单独的编译(恕我直言),而是停止问题。即,即使你看到所有的程序文本,它在理论上也是不可能的。
答案 1 :(得分:2)
值限制非常简单:只有语法值的let-bound表达式才是通用的。应用程序(包括部分应用程序)不是值,因此不是一般化的。
请注意,通常无法判断应用程序是否是部分的,因此应用程序是否会对引用单元格的值产生影响。当然,在这种特殊情况下,很明显没有这样的事情发生,但推理规则被设计为在它发生的情况下是合理的。
答案 2 :(得分:2)
'let'表达式不是(语法)值。虽然存在precise definition'value',但大致唯一的值是应用于值的标识符,函数,常量和构造函数。
This paper及其引用的内容详细解释了问题。
答案 3 :(得分:1)
部分申请并不排除突变。例如,以下是您的代码的重构版本,如果没有值限制也是错误的:
let aux cache x =
match !cache with
| Some y -> y
| None -> cache := Some x; x
let remember = aux (ref None)