我试图让这个非常简单的SML功能的尾递归版本:是什么导致此Standard-ML类型错误?
fun suffixes [] = [[]]
| suffixes (x::xs) = (x::xs) :: suffixes xs;
在这个过程中,我使用的PARAMATERS类型注释。下面的代码显示了这一点,并导致了一个类型错误(下面给出),而如果我只是删除类型注释,SML接受它没有问题,给整个函数与上面更简单的函数相同的签名。
fun suffixes_tail xs =
let
fun suffixes_helper [] acc = []::acc
| suffixes_helper (x::xs:'a list) (acc:'b list) =
suffixes_helper xs ((x::xs)::acc)
in
suffixes_helper xs []
end;
错误:
$ sml typeerror.sml
Standard ML of New Jersey v110.71 [built: Thu Sep 17 16:48:42 2009]
[opening typeerror.sml]
val suffixes = fn : 'a list -> 'a list list
typeerror.sml:17.81-17.93 Error: operator and operand don't agree [UBOUND match]
operator domain: 'a list * 'a list list
operand: 'a list * 'b list
in expression:
(x :: xs) :: acc
typeerror.sml:16.13-17.94 Error: types of rules don't agree [UBOUND match]
earlier rule(s): 'a list * 'Z list list -> 'Z list list
this rule: 'a list * 'b list -> 'Y
in rule:
(x :: xs : 'a list,acc : 'b list) =>
(suffixes_helper xs) ((x :: xs) :: acc)
/usr/local/smlnj-110.71/bin/sml: Fatal error -- Uncaught exception Error with 0
raised at ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
有给出了两个错误。后者在这里似乎不那么重要,后缀的两个子句之间不匹配。第一个是我不明白的。我注释说第一个参数的类型是'a:list
,第二个参数的类型是'b:list
。我不知道Hindley-Milner类型推理算法是否能够统一'b:list
与'a:list list
,使用替代'b ---> 'a list
?
编辑:一个答案表明它可能与类型推断算法有关,不允许推断类型,这在某种意义上比类型注释给出的类型更严格。我猜想这样的规则只适用于参数和函数的注释。我不知道这是否正确。在任何情况下,我尝试过的函数体移动式注解,我也得到了同样类型的错误:
fun suffixes_helper [] acc = []::acc
| suffixes_helper (x::xs) acc =
suffixes_helper (xs:'a list) (((x::xs)::acc):'b list);
的错误,现在是:
typeerror.sml:5.67-5.89 Error: expression doesn't match constraint [UBOUND match]
expression: 'a list list
constraint: 'b list
in expression:
(x :: xs) :: acc: 'b list
谢谢,那是我没有考虑过的事情:当参数中给出类型注释时,类型推断可能被实现为不允许比给定参数更严格的推断类型。但是,如果将类型注释放入函数体内,我会遇到同样的错误。我将编辑我的问题以显示此内容。 – harms 2009-12-06 00:35:34
你仍然注释一个比推断类型更不严格的类型 – 2009-12-06 00:51:43