SML运算符和操作数在foldr中不一致

时间:2016-10-12 13:01:16

标签: sml smlnj

我正在进行一项任务,我必须编写一个函数来获取列表的长度。这是一项微不足道的任务,但我遇到了一些我不理解的事情。

我的简单代码

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

但我想了解为什么第一个版本不起作用。

1 个答案:

答案 0 :(得分:3)

这是value restriction规则应用程序的一个实例:

  

简而言之,值限制表明,只有当表达式的右侧在语法上是一个值时,才会发生泛化。

在语法上,

foldr (fn(_, y) => y + 1) 0

不是一个值,它是一个函数应用程序,这就是为什么它没有被赋予多态类型的原因。它已经用虚拟类型实例化,其使用非常有限,例如,这有效:

len []

但在大多数情况下len定义为val是没用的。

这种限制的存在是为了在存在变量赋值(通过引用)的情况下保证类型安全。更多详细信息可以在链接页面中找到。