警告で言及されている値の制限は、SML で理解するのが難しいものの 1 つですが、この場合にそれが発生する理由を説明し、詳細を学ぶためにいくつかのリソースを紹介するように最善を尽くします.
ご存じのとおり、SML は型推論を使用して、プログラム内のほとんどの型を推測します。このプログラムでは、 の型は でmy_func
あると推測されます('a -> 'b option) -> 'a list -> 'b
。ご指摘のとおり、これはポリモーフィック型です。my_func
このように電話すると
myfunc f [NONE, SOME 1, NONE];
... 型変数'a
and'b
は and にインスタンス化されint option
ますint
。
SOME 1
ただし、上記のような値なしで呼び出すと
myfunc f [NONE, NONE];
型変数は何にインスタンス化する必要があると思いますか? 型はポリモーフィックである必要があります。すべての型に対して't option
andのようなものです。ただし、このような値がポリモーフィック型になるのを防ぐ制限があります。'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