質問

私はこの非常に単純なSML関数の末尾再帰バージョンを作成しようとしていた。

fun suffixes [] = [[]]
  | suffixes (x::xs) = (x::xs) :: suffixes xs;

このの過程で、私はPARAMATERSに型注釈を使用していました。次のコードはこれを示し、Iは、単にタイプの注釈を削除する一方、(下記の)タイプエラーが発生し、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 paramは型'b:listであることであることを述べるために注釈を付けます。私はそれを理解して、一般的な統一の上部に構築されたヒンドリー - ミルナー型推論アルゴリズムは、'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
役に立ちましたか?

解決

私はSMLわからないけど、F#、他の関数型言語、このような状況で警告を与えます。エラーを与えることは少し厳しいことが、それは理にかなっていることがあります。プログラマは、余分なタイプの変数紹介する場合は、「Bを、そして場合は、」bがリスト」タイプのものでなければならないプログラマが意図したように、関数は、一般的なようではない可能性があります価値の報告がある。

他のヒント

この作品ます:

fun suffixes_tail xs =
    let
        fun suffixes_helper [] acc = []::acc
          | suffixes_helper (x::xs:'a list) (acc:'a list list) =
                suffixes_helper xs ((x::xs)::acc)
    in
        suffixes_helper xs []
    end

ヨハとnewacctとしては'b listが緩すぎる、と言います。明示的な型注釈を与えた場合、

fun suffixes_helper (_ : 'a list) (_ : 'b list) = ...

これは、暗黙のうちに

として定量化されます
fun suffixes_helper (_ : (All 'a).'a list) (_ : (All 'b).'b list) = ...

と明らかに'b = 'a listは同時に(All a')(All b') trueにすることはできません。

明示的な型注釈がなければ、型推論は、種類を統一することで正しいことを、行うことができます。そして実際に、SMLの型システムは、そのように明示的な型注釈が必要になることはありません、決定不能になることはありません(私の知る限り承知のように)ということは十分に簡単です。なぜ、あなたはここに入れたいのですか?

あなたは'a'bがの、の独立は、のものに設定することができることを意味し'a'b、のようなタイプの変数を使用する場合。私は'bint'afloatであったことを決めたのであれば、たとえばそれが動作するはずです。それは'b'a listしなければならないことが判明したので、しかし、明らかに、それはこの場合には有効ではありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top