Ocaml 为什么;“咖喱”;需求问题?
我正在阅读这张幻灯片,我在这里发现了一个有趣的问题: 似乎oops函数会生成编译错误:Ocaml 为什么;“咖喱”;需求问题?,ocaml,currying,Ocaml,Currying,我正在阅读这张幻灯片,我在这里发现了一个有趣的问题: 似乎oops函数会生成编译错误: the type of this expression contains type variables that cannot be generalized 我不知道原因,所以我在Mac上使用OCaml 4.01.0版快速对该函数进行了一些测试,令我惊讶的是,我在解释该代码时没有看到任何错误 我不知道为什么幻灯片声称这是一个错误,因为咖喱,我不能重新创建这个错误 有人能给我一些帮助吗?编译器抱怨这个错误,
the type of this expression contains type variables that cannot be generalized
我不知道原因,所以我在Mac上使用OCaml 4.01.0版快速对该函数进行了一些测试,令我惊讶的是,我在解释该代码时没有看到任何错误
我不知道为什么幻灯片声称这是一个错误,因为咖喱,我不能重新创建这个错误
有人能给我一些帮助吗?编译器抱怨这个错误,但顶层没有
$ cat ungen.ml
open List
let oops = fold_left (fun a _ -> a + 1) 0
$ ocamlc -c ungen.ml
File "ungen.ml", line 2, characters 11-41:
Error: The type of this expression, '_a list -> int,
contains type variables that cannot be generalized
问题仍然存在于顶层;如果您尝试使用oops
计算两个不同类型列表的长度,您会看到:
$ ocaml
OCaml version 4.01.0
# open List;;
# let oops = fold_left (fun a _ -> a + 1) 0;;
val oops : '_a list -> int = <fun>
# oops [1;2;3;4];;
- : int = 4
# oops ['a';'b';'c'];;
Error: This expression has type char but an expression was expected of type
int
#
如果允许mylist
具有类型'a list ref
,则可以在其中存储所有不同类型的列表,这是不安全的
然而,这是可以概括的:
let mylist2 = []
将mylist2
概括为类型'a列表
没有问题
在像OCaml这样的现代ML衍生工具中,对泛化的限制已经减少到或多或少的简单规则。“值”(如[]
)可以泛化。不是值的表达式(如ref[]
)不能通用化
表达方式:
fold_left (fun a _ -> a + 1) 0
fun xs -> fold_left (fun a _ -> a + 1) 0 xs
这不是一个值。这是一个函数应用程序,具有与ref[]
相同的粗略形式。这(显然)就是上面的oops
的定义
另一方面,表达式:
fold_left (fun a _ -> a + 1) 0
fun xs -> fold_left (fun a _ -> a + 1) 0 xs
是一种价值;这是一辆兰巴。所以它可以被推广。这(在展开一个方便的语法缩写后)就是上面len
的定义。这就是为什么len
适用于所有列表,但是oops
没有那么有用
值和非值之间的区别是句法上的;i、 例如,可以通过局部查看表达式的形式来确定。你不需要知道表达式的类型或含义就可以做出决定
使用当前形式的值限制的一个理由是,在大多数情况下,通过以len
的形式而不是oops
的形式定义函数,可以恢复所需的函数泛化(即多态性)。这种简单的转换称为“eta扩展”
eta扩展只改变语法而不改变函数的含义这一事实表明,值限制只是一个近似值。也就是说,它禁止泛化一些可以安全地泛化的表达式。但是它很好而且简单,在实际程序中发生的情况下没有太多限制
自OCAML3.07以来,OCaml的值限制已从基本ML改进,因为它允许在更多情况下进行泛化。您可以在此处阅读:。这篇论文还包含了价值限制及其历史的优秀总结。嗨,杰弗里,非常感谢你的回答!但基本上为什么编译器不允许它。。?从这张幻灯片的开头来看,这是因为与“咖喱”有关的事情。。?我知道“咖喱”的基本概念,但我只是不知道为什么在这种情况下“咖喱”很重要?