Jeffrey は、緩和が正しい理由について直感的な説明を提供しました。それがいつ役立つかについては、最初に回答octrefを再現できると思います。
いつか、自分の抽象型が思ったほどポリモーフィックではないという問題に遭遇するまでは、これらの微妙な点を安全に無視してもかまいません。その場合は、署名の共分散注釈が役立つ可能性があることを覚えておく必要があります。
これについては、数か月前に reddit/ocaml で議論しました。
次のコード例を検討してください。
module type S = sig
type 'a collection
val empty : unit -> 'a collection
end
module C : S = struct
type 'a collection =
| Nil
| Cons of 'a * 'a collection
let empty () = Nil
end
let test = C.empty ()
取得する型test
は、期待する'_a C.collection
ではなく です。'a C.collection
これは多相型 ('_a
まだ完全には決定されていない単相推論変数) ではなく、ほとんどの場合、これに満足することはありません。
これは、C.empty ()
が値ではないため、その型が一般化されていない (~ ポリモーフィックにされている) ためです。緩和された値の制限の恩恵を受けるには、抽象型'a collection
共変をマークする必要があります。
module type S = sig
type +'a collection
val empty : unit -> 'a collection
end
もちろん、これはモジュールC
が署名で封印されているためにのみ発生しますS
: module C : S = ...
. モジュールC
に明示的な署名が与えられていない場合、型システムは最も一般的な分散 (ここでは共分散) を推測し、それに気付かないでしょう。
抽象インターフェースに対するプログラミングは、(ファンクターを定義するとき、またはファントム型規則を強制するとき、またはモジュラー プログラムを作成するとき) に役立つことが多いため、この種の状況は確実に発生し、緩和された値の制限について知っておくと役立ちます。
これは、より多くのポリモーフィズムを取得するためにそれを認識する必要がある場合の例です。抽象境界 (抽象型のモジュール シグネチャ) を設定し、それが自動的に機能しないため、抽象型を明示的に指定する必要があるためです。は共変です。
ほとんどの場合、ポリモーフィックなデータ構造を操作するときに、気付かないうちに発生します。緩和のおかげで[] @ []
多形型しかありません。'a list
具体的だがより高度な例は、Oleg の Ber-MetaOCaml です。これは、型を使用して、('cl, 'ty) code
区分的に構築された引用符で囲まれた式を表します。'ty
は、引用されたコードの結果の型を表し、'cl
多態性のままである場合、引用されたコード内の変数のスコープが正しいことを保証する一種のファントム領域変数です。これは、引用された式が他の引用された式を構成することによって構築される状況でのポリモーフィズムに依存するため (したがって、一般的には値ではありません)、基本的には、値の制限を緩和しないとまったく機能しません (これは、型に関する彼の優れたまだ技術的なドキュメントの補足的な発言です)。推論)。