我正在进行一项任务,我必须编写一个函数来获取列表的长度。这是一项微不足道的任务,但我遇到了一些我不理解的事情。
我的简单代码
val len = foldr (fn(_, y) => y + 1) 0
产生此警告
警告:因为而未输入广义类型的变量 值限制被实例化为虚拟类型(X1,X2,...)
当我尝试在REPL中运行它时,我得到了这个:
len [1, 2, 3, 4];
stdIn:18.1-18.17 Error: operator and operand don't agree [overload conflict]
operator domain: ?.X1 list operand:
[int ty] list in expression:
len (1 :: 2 :: 3 :: <exp> :: <exp>)
我不明白为什么这不起作用。我确实知道一些函数式编程原理,这应该可行,因为它非常简单的部分应用程序。
当然,我可以在没有部分应用的情况下使其工作,例如
fun len xs = foldr (fn(_, y) => y + 1) 0 xs
但我想了解为什么第一个版本不起作用。
答案 0 :(得分:3)
这是value restriction规则应用程序的一个实例:
简而言之,值限制表明,只有当表达式的右侧在语法上是一个值时,才会发生泛化。
在语法上,
foldr (fn(_, y) => y + 1) 0
不是一个值,它是一个函数应用程序,这就是为什么它没有被赋予多态类型的原因。它已经用虚拟类型实例化,其使用非常有限,例如,这有效:
len []
但在大多数情况下len
定义为val
是没用的。
这种限制的存在是为了在存在变量赋值(通过引用)的情况下保证类型安全。更多详细信息可以在链接页面中找到。