この非常に単純なSML関数の末尾再帰バージョンを作成しようとしていました。
fun suffixes [] = [[]]
| suffixes (x::xs) = (x::xs) :: suffixes xs;
この過程で、私はパラメータに型注釈を使用していました。次のコードはこれを示しており、タイプエラーが発生します(以下を参照)が、タイプアノテーションを削除するだけで、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
与えられた2つのエラーがあります。後者はここではそれほど重要ではないようです。suffixes_helperの2つの句の不一致です。最初は私が理解していないものです。'a:list
最初のパラメータがタイプであり、2番目のパラメータがタイプであることを示すために注釈を付け'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