价值限制

时间:2014-03-19 13:29:56

标签: ocaml

在OCaml中,您无法概括部分应用的curried函数(“值限制”)。

价值限制的目的是什么?如果它不存在会发生什么不愉快?

3 个答案:

答案 0 :(得分:18)

如果没有限制泛化的限制或其他机制,类型系统将接受该程序:

let r = (fun x -> ref x) [];; (* this is the line where the value restriction would trigger *)

> r : 'a list ref

r := [ 1 ];;

let cond = (!r = [ "foo" ]);;

变量r的类型为'a list ref,这意味着它的内容可以与[ "foo" ]进行比较,尽管它包含一个整数列表。

请参阅Xavier Leroy's PhD thesis了解更多动机(ref不是唯一可能想要添加到引入问题的纯lambda演算中的构造)以及对当前存在的系统的调查他的论文(包括他的论文)。

答案 1 :(得分:9)

Here是我前段时间给出的关于F#的答案;问题与OCaml完全相同。问题是如果没有它,我们将能够创建指向错误类型数据的引用:

let f : 'a -> 'a option =
    let r = ref None in
    fun x ->
        let old = !r in
        r := Some x;
        old

f 3           // r := Some 3; returns None : int option
f "t"         // r := Some "t"; returns Some 3 : string option!!!

答案 2 :(得分:2)

weakly polymorphism here(side-effects-and-weak-polymorphism)有一个很好的描述。

基本上,让我们来看看下面的函数(缓存它看到的第一个值):

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

由于涉及必要,因此应用值限制


然而,让我们假设没有价值限制。

然后它的类型变为val remember : 'a -> 'a = <fun>


如果我现在let () = remember 11会记录在cache内,对吗?

如果我第二次呼叫let x = 3 + remember 2,这应该有效,因为3是整数,remember返回与其参数相同的类型。我在这里给2,所以remember也返回整数(但是值已经是我们已经记住过的一次)。这应该通过类型检查。


如果我第3次呼叫let y = 3.0 + remember 2.0怎么办?它会再次起作用吗?

根据记住的类型和我第二次调用背后的原因,它也应该有效,因为我给了remember浮点数,它应该返回浮点数。

但是因为第一次将1(整数)存储在内部,它将返回1,这是一个整数。所以类型检查会失败,对吗?


我们可以看到,没有值限制或弱多态,由于允许可变性,整个类型检查会有麻烦。在上面的愚蠢案例中,您需要不断手动检查或跟踪存储的初始类型remember