SML 运算符和操作数在文件夹中不一致

SML Operator and operand don't agree in foldr

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

我的简单代码

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

产生此警告

Warning: type vars not generalized because of value restriction are instantiated to dummy types (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

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

这是 value restriction 规则应用的实例:

In short, the value restriction says that generalization can only occur if the right-hand side of an expression is syntactically a value.

语法上,

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

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

len []

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

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