特にOCamlに関して、さまざまなタイプのポリモーフィズムを理解するのに問題があります。ポリモーフィズムにより、OCaml で 'a として示される複数のタイプが許可されることは理解していますが、さまざまなタイプのポリモーフィズムが何であるかはわかりません。
誰かが比較的低レベルな言葉で説明してくれたら最高です! アドホック、パラメトリック、包含/サブタイピング
3 に答える
これが概算です。
アドホック ポリモーフィズムとは通常、同じ名前 (通常は関数) を異なる型 (たとえばSML+ : int -> int -> int
など) で宣言できることを指します。+ : float -> float -> float
これらは異なる関数であり、まったく異なる方法で動作する可能性がありますが、コンパイラまたはインタープリターはコンテキストに応じて適切なものを選択します。OCaml でのアドホック ポリモーフィズムの例は思い浮かびません。ただし、C++ と Java では一般的です。
パラメトリック ポリモーフィズムとは、引数の構造を調べようとしないために、単一の関数が任意の型の引数を処理できる場合です。たとえば、同じ型の値のリストに任意の型のcons : 'a -> 'a list -> 'a list
値を追加できます。これは、構造 (レイアウト) が何であるか、またはそれがサポートする操作が何であるかv
は問題ではないためです。C 用語では、ポインターを「逆参照」する必要はなく、実際の型に固有の操作を実行する必要もありません。アドホック ポリモーフィズムとは異なり、cons
v
cons
v
v
cons
すべてのタイプに対して同じように動作します。したがって、パラメトリックおよびアドホック ポリモーフィズムは、ある意味で互いに「正反対」です。パラメトリック ポリモーフィズムは、OCaml におけるポリモーフィズムのインスタンスの大多数の原因となっています。
サブタイプ ポリモーフィズムとは、型の値が期待されるt
場所で型の値を使用できる場合です。u
これは、 type が typet
のすべての操作をサポートしているu
、またはt
の構造がu
期待される場所で使用できるためである可能性があります。この例としては、サブクラス化 (おそらく、Vehicle が使用できる場所ならどこでも Bus を使用できます)、またはポリモーフィック バリアント (期待される'A | 'B
場所で使用できます'A | 'B | 'C
) があります。
コメントごとに編集
ただし、サブタイプは OCaml で明示的に要求する必要があることに注意してください。たとえば、関数があり、それをのサブタイプであるf : u -> int
に適用したい場合v : t
は、 と書く必要があります。構文は型強制です。t
u
f (v :> u)
(v :> u)
OCaml は行ポリモーフィズムもサポートしています。これは、制約付きのパラメトリック ポリモーフィズムの一種です。f
代わりに がf : #u -> int
(オブジェクト型の場合) またはf : [< u] -> int
(ポリモーフィック バリアントの場合) の場合、#u
/[< u]
構文は と同様の型変数を表しますが、より多くのフィールドをサポートできるという制限された意味で'a
、それぞれの「サブタイプ」にのみ置き換えることができます。 u
/less コンストラクター、それぞれ)。f v
そうすれば、強制なくできます。OCaml は、ポリモーフィック バリアントとオブジェクトを含む多くの式に対して、行ポリモーフィズムを使用する型を自動的に推論しますが、署名を作成する場合は、型を明示的に記述する必要があります。
行ポリモーフィズムには、さらに多くの使用法と考慮事項があります。実際の行変数と追加の構文を無視し、(Java ジェネリックのように) 有界量化のように見えるものだけを説明しました。行ポリモーフィズム、その名前、および/またはその形式に関するより詳細で正確な議論は、おそらく別の質問のために保存するのが最善です.
ident は多形性です:
# let ident x = x;;
val ident : 'a -> 'a = <fun>
# ident 1;;
- : int = 1
# ident "ok";;
- : string = "ok"
# ident [];;
- : 'a list = []
# ident List.length;;
- : '_a list -> int = <fun>
# ident ident;;
- : '_a -> '_a = <fun>
折りも:
# open List;;
# fold_left (+) 0 [1;2;3];;
- : int = 6
# fold_left (^) "" ["1";"2";"3"];;
- : string = "123"
# fold_left (fun a (x,y) -> a+x*y) 0 [(1,2);(3,4);(5,6)];;
- : int = 44