警告中引用的值限制是在 SML 中更难理解的事情之一,但是我会尽力解释为什么会在这种情况下出现,并尝试向您指出一些资源以了解更多信息。
如您所知,SML 将使用类型推断来推断程序中的大多数类型。在这个程序中,类型my_func
将被推断为('a -> 'b option) -> 'a list -> 'b
. 正如您所指出的,它是一种多态类型。当你my_func
这样打电话时
myfunc f [NONE, SOME 1, NONE];
...类型变量'a
and'b
被实例化为int option
and int
。
但是,当您在没有上述值的情况下调用它SOME 1
时
myfunc f [NONE, NONE];
你认为类型变量应该被实例化成什么?类型应该是多态的——类似于所有类型的't option
和。但是,有一个限制可以防止像这样的值采用多态类型。't
't
SML 将一些表达式定义为非扩展值,并且只有这些值可以采用多态类型。他们是:
- 文字(常量)
- 变量
- 函数表达式
- 构造函数(除了
ref
)应用于非扩展值
- 带有类型注释的非扩展值
- 每个字段都是非扩展值的元组
- 每个字段都是非扩展值的记录
- 列出每个字段是非扩展值的位置
所有其他表达式,特别是函数调用(这是调用的my_func
内容)不能是多态的。也不能参考。您可能会好奇地看到以下内容不会引发警告:
fn () => my_func f [NONE, NONE];
相反,推断的类型是unit -> 'a
. 但是,如果您要调用此函数,您将再次收到警告。
我对这种限制原因的理解有点薄弱,但我相信潜在的根本问题是可变引用。这是我从下面链接的 MLton 站点中获取的示例:
val r: 'a option ref = ref NONE
val r1: string option ref = r
val r2: int option ref = r
val () = r1 := SOME "foo"
val v: int = valOf (!r2)
由于值限制,此程序不会在 SML 下进行类型检查。如果不是值限制,这个程序在运行时会出现类型错误。
正如我所说,我的理解是不稳定的。但是,我希望我对您遇到的问题有所了解,尽管我相信在您的情况下,您可以放心地忽略警告。如果您决定要深入挖掘,这里有一些参考资料:
http://users.cis.fiu.edu/~smithg/cop4555/valrestr.html
http://mlton.org/ValueRestriction
(顺便说一句,MLton 网站是纯金的。这里隐藏了很多东西,所以如果你想了解一些关于 SML 的奇怪之处,我强烈建议在这里搜索,因为你可能会出现比你最初想要的更多的东西)
因为看起来你实际上是在使用 SML/NJ,所以这是一个非常方便的指南,可以帮助你在编译时给出错误消息和警告:
http://flint.cs.yale.edu/cs421/smlnj/doc/errors.html