12

宿題の問題で、次の SML 関数が警告をスローする理由を、一生理解できません。

fun my_func f ls  = 
  case ls of 
  [] => raise MyException
  | head :: rest => case f head of 
                    SOME v => v
                    | NONE => my_func f rest

fun f a = if isSome a then a else NONE;

次のテスト関数で my_func を呼び出すたびに:

my_func f [NONE, NONE];
my_func f [];

私はいつも警告を受け取ります:

警告: 値の制限のために一般化されていない型変数は、ダミーの型 (X1、X2、...) にインスタンス化されています

少なくとも 1 つの SOME 値を含むオプション リストを渡すたびに、この警告はスローされません。関数のカリー化でポリモーフィズムを使用しているという事実と関係があるに違いないことはわかっていますが、これらの警告を取り除く方法については完全に行き詰まっています。

何かアイデアがあれば助けてください - よろしくお願いします!

4

1 に答える 1

23

警告で言及されている値の制限は、SML で理解するのが難しいものの 1 つですが、この場合にそれが発生する理由を説明し、詳細を学ぶためにいくつかのリソースを紹介するように最善を尽くします.

ご存じのとおり、SML は型推論を使用して、プログラム内のほとんどの型を推測します。このプログラムでは、 の型は でmy_funcあると推測されます('a -> 'b option) -> 'a list -> 'b。ご指摘のとおり、これはポリモーフィック型です。my_funcこのように電話すると

myfunc f [NONE, SOME 1, NONE];

... 型変数'aand'bは and にインスタンス化されint optionますint

SOME 1ただし、上記のような値なしで呼び出すと

myfunc f [NONE, NONE];

型変数は何にインスタンス化する必要があると思いますか? 型はポリモーフィックである必要があります。すべての型に対して't optionandのようなものです。ただし、このような値がポリモーフィック型になるのを防ぐ制限があります。't't

SML は一部の式を非拡張値として定義し、これらの値のみが多相型を取ることができます。彼らです:

  • リテラル (定数)
  • 変数
  • 関数式
  • ref非拡張値に適用されるコンストラクター ( を除く)
  • 型注釈付きの非拡張値
  • 各フィールドが非拡張値であるタプル
  • 各フィールドが非拡張値であるレコード
  • 各フィールドが非拡張値であるリスト

他のすべての式、特に関数呼び出し(これは への呼び出しmy_funcです)は polymorphic にすることはできません。どちらも参照できません。次の場合、警告が発生しないことに興味があるかもしれません。

 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

于 2013-02-03T04:43:54.097 に答える