2013-03-09 4 views
14

ocamlの標準ライブラリをブラウズしていて、このコードをmap.mlファイルに置いていました。このタイプの前にプラス記号があるのはなぜですか?

module type S = 
    sig 
    type key 
    type +'a t 
    val empty: 'a t' 

type +'a tがあるなぜ私は思ったんだけど、なぜ著者はそれを使用する代わりに、単に'a t
その動作は奇妙で、私はそれの使用法を推測することはできません。

# type +'a t = 'a list;; 
type 'a t = 'a list 
# type +'a t = +'a list;; 
Characters 13-14: 
    type +'a t = +'a list;; 
      ^
Error: Syntax error 

おかげ

+0

関連記事Jane Streetから:https://blogs.janestreet.com/a-and-a/ –

答えて

14

、ここで共変は、あなたがサブタイプを使用する際に役立つそうではないとして、開発者が抽象型のマーキングの仕事をした理由は、(基本的に誰もが、OCamlの中でサブタイプを使用していません)、共分散抽象型がより多形性を可能にする「緩和された値の制限」と呼ばれるタイプシステムのよりよく知られていない側面を使用することです。

多分、多態性ではない抽象型の問題をヒットするまで、これらの微妙な要素を無視しても問題ありません。署名の共分散注釈よりも覚えておく必要があります。

我々は数ヶ月前にこのon 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()は値ではないため、その型は一般化されていません(〜made polymorphic)。

module type S = sig 
    type +'a collection 
    val empty : unit -> 'a collection 
end 

モジュールCが署名Sで封止されているので、これはのみ発生もちろん:module C : S = ...リラックスした値の制限の恩恵を受けるためには、抽象型'a collection共変をマークする必要があります。モジュールCに明示的な署名が与えられていなければ、型システムは最も一般的な分散(ここでは共分散)を推論し、それに気づかないだろう。

抽象的なインターフェースに対するプログラミングは、この種の状況が確実に起こるように、(ファンクタを定義したり、ファントム型の規律を適用したり、モジュール式のプログラムを書くときに)しばしば役に立ち、緩やかな値の制限について知っておくと便利です。あなたは理論を理解したい場合は

、値の制限とその緩和は、最初の数ページのトピックと主要な考え方にかなり面白いとアクセス導入されているジャック・Garrigueの、年から2004年の研究論文Relaxing the value restrictionで議論されています。

+0

詳細な説明をありがとう。私はmap.mlに戻り、次の行を見つけました:type 'a t = Empty |あなたの例に非常によく似ている 't *キー*' a * 't * intのノード。しかし、単相推論型についてもっと説明できますか? 「_a C.collectionはまだC.collectionに一致しているようです。 C.empty()の型が一般化されていない場合、いつどのような問題が発生するのでしょうか? – octref

+2

@octref:タイプ '' _a - > '_a'を持つ 'let id =(fun x - > x)(fun x - > x)'を使うようにしてください。(その定義はaその型変数は正と負の両方の位置で発生します)。問題はすぐにわかります.2つの異なるタイプでは使用できないため、多態性はありません。 – gasche

+0

ありがとうございましたgasche、これは本当に知って良いです。私はそれが普通の古いサブタイプについてしか考えていないことを想像しました。 –

12

これは、モジュール・タイプに対して共変などのタイプをマーク。同じタイプのキーを持つ2つのマップがあるとします。この+は、あるマップAの値が他のマップBの値のサブタイプである場合、マップAの全体のタイプはマップBのタイプのサブタイプであると言います。私はJane Street blogでこれについてのかなり良い説明を見つけました。パラメトリックpolymorphisが一般的に好まれるようジェフリーの答えに構築する

+0

マップAが地図Bのタイプのサブタイプである場合、その方法は次のようになります。 B on A?それはJavaのサブクラス概念に似ていますか? – octref

+1

OCamlの非OO部分はJavaと全く似ていません。 Javaのサブクラス化*はサブタイプの一種ですが、サブクラス化はJavaの重要な機能ですが、サブタイプの使用はOCamlではまれですOCamlはサブタイプを推論しないことに注意してください。式の型をスーパータイプに明示的に変換する必要があります。それはほとんど決して上がることがないので、これは問題ありません。しかし、これを行うとyesになり、(メソッドだけでなく、すべての関数)スーパータイプに定義された関数をサブタイプに適用することができます。 –

+0

あなたの説明をありがとう! – octref

関連する問題