プログラミング言語と型理論では、パラメトリック多相性により、実際の型の代わりに変数を使用して単一のコードに「汎用」型を与え、必要に応じて特定の型でインスタンス化することができます。[ 1 ] : 340パラメトリック多相性関数とデータ型は、それぞれ汎用関数と汎用データ型と呼ばれることがあり、汎用プログラミングの基礎を形成します。
パラメトリック多相性は、アドホック多相性とは対照的です。パラメトリック多相性の定義は均一です。つまり、インスタンス化される型に関係なく、同じように動作します。[ 1 ] : 340 [ 2 ] : 37一方、アドホック多相性の定義は、型ごとに異なる定義が与えられます。そのため、アドホック多相性は、型ごとに個別の実装を提供する必要があるため、一般的に限られた数の異なる型しかサポートできません。
パラメトリック多相性を研究するための一般的な理論的手法はシステムFであり、これは単純な型付きラムダ計算を型に対する量化で拡張したものである。
引数の型に依存しない関数を記述することは可能です。例えば、恒等関数などが挙げられます。引数をそのまま返します。これにより、次のような潜在的な型のファミリーが自然に生まれます。、、など。パラメトリック多相性により全称量化型変数を導入することにより、単一の最も一般的な型を与える:
多相定義は、任意の具体的な型を代入することでインスタンス化できます。これにより、潜在的な型の全ファミリーが得られます。[ 3 ]
恒等関数は特に極端な例ですが、他の多くの関数もパラメトリック多相性の恩恵を受けています。たとえば、2 つのリストを連結する関数は、リストの要素を検査せず、リストの構造自体のみを検査します。したがって、類似の型ファミリーを与えることができます。、などなど、型の要素のリストを表します最も一般的なタイプは
これは、ファミリー内の任意の型にインスタンス化できます。
パラメトリック多相関数そして任意の型でパラメータ化されていると言われている[ 4 ]両方そしては単一の型でパラメータ化されますが、関数は任意の数の型でパラメータ化できます。たとえば、そしてペアの最初の要素と2番目の要素をそれぞれ返す関数には、以下の型を指定できます。
表現において、インスタンス化されるそしてインスタンス化される呼び出しの中で全体の式の型は。
パラメトリック多相性を導入するために使用される構文は、プログラミング言語によって大きく異なります。たとえば、Haskellなどの一部のプログラミング言語では、量化子は暗黙的であり、省略できます。[ 5 ]他の言語では、パラメトリック多相関数の呼び出し箇所で型を明示的にインスタンス化する必要があります。すべての箇所でインスタンス化するか、少なくとも型推論によって残りの部分を決定できるだけの十分な箇所でインスタンス化する必要があります。
パラメトリック多相性は、1975 年に ML で初めてプログラミング言語に導入されました。[ 6 ]現在では、Standard ML、OCaml、F#、Ada、Haskell、Mercury、Visual Prolog、Scala、Julia、Python、TypeScript、C++などに存在します。Java 、C#、Visual Basic .NET、Delphi はそれぞれ、パラメトリック多相性のための「ジェネリクス」を導入しています。型多相性の実装の中には、表面上はパラメトリック多相性に似ているものの、アドホックな側面も導入しているものがあります。その一例がC++テンプレート特殊化です。
1980年代、LeivantはGirardとReynoldsのシステムFの階層化(つまり述語的)バージョンを導入した。Leivantのアプローチは、関数コンストラクタ内のネスト深度を測定する量化子のランクの概念に基づいている。[ 7 ]この観点から、MLアプローチはランク1多相性に限定される。Haskellは1990年代に高ランクのパラメトリック多相性を採用した。例えば、Haskellではランク2のパラメトリック多相性を使用してモナドを定義しておりrunST、これは「命令型プログラミングの分離された領域」を持つ型と効果のシステムを効果的にシミュレートしている。[ 8 ]型レベルでは、状態の分離は基本的に、における状態に対するより深いランク2の量化から生じるrunST。(これだけでは、の実行時意味論を形式的に記述するには不十分であるrunST。後者については、分離論理などの追加の要素が必要となる。[ 9 ])
型は、そのルートから次の要素へのパスが存在しない場合、ランクk (固定整数kに対して) であると言われます。量指定子は、型が木として描かれている場合、k個以上の矢印の左側に渡されます。 [ 1 ] : 359型システムがランクk多相性をサポートするとは、ランクがk以下の型を許容する場合を指します。たとえば、ランク 2 多相性をサポートする型システムは、しかしそうではない任意のランクの型を許容する型システムは、「ランクn多相的」であると言われる。
(このランクの概念は、古典論理における量化子ランクの定義とは異なります。なぜなら、ここでは非量化子結合子に対する入れ子の深さを測定するのに対し、古典論理では非量化子結合子はそれらの下にネストされた量化子のランクを増加させませんが、他の量化子は増加させるからです。)
述語型システム(プレネックス多相システムとも呼ばれる)では、型変数を多相型でインスタンス化することはできません。[ 1 ]: 359-360述語型理論には、Martin-Löf 型理論とNuprlがあります。これは、「ML スタイル」または「Let 多相」と呼ばれるものと非常によく似ています(厳密には、ML の Let 多相には、他にもいくつかの構文上の制約があります)。この制約により、多相型と非多相型の区別が非常に重要になります。そのため、述語システムでは、多相型は、通常の(単相)型(単型と呼ばれることもあります)と区別するために、型スキーマと呼ばれることがあります。
述語性の結果として、すべての型は、すべての量化子を最も外側の(前置)位置に配置する形式で記述できます。たとえば、上記で説明した関数は、以下の型を持ちます。
この関数をリストのペアに適用するには、具体的な型変数の代わりに結果として得られる関数型が引数の型と一致するようにする。非述語システムでは、は、それ自体が多相的な型を含む、あらゆる型になり得る。したがってあらゆる型の要素を持つリストのペアに適用できます。多相関数のリストにも適用できます。それ自体。言語 ML の多相性は述語的です。[ 10 ]これは、述語性が他の制約と相まって、型システムが十分に単純になり、完全な型推論が常に可能になるためです。
実例として、OCaml ( MLの派生言語または方言)は型推論を実行し、非述語的多相性をサポートしていますが、非述語的多相性が使用される場合、プログラマが明示的な型注釈を提供しない限り、システムの型推論が不完全になることがあります。
一部の型システムは、他の型コンストラクタが述語的であるにもかかわらず、非述語的な関数型コンストラクタをサポートしています。たとえば、型上位多相性をサポートするシステムでは許可されていますが、そうではないかもしれない。[ 11 ]
ランク2多相性の型推論は決定可能であるが、ランク3以上の場合は決定不可能である。[ 12 ] [ 1 ]: 359
非述語的多相性(第一級多相性とも呼ばれる)は、パラメトリック多相性の最も強力な形式です。[ 1 ]: 340形式論理では、定義が自己参照的である場合、非述語的であると言われます。型理論では、型がそれに含まれる量化子の領域に属する能力を指します。これにより、多相型を含む任意の型変数を任意の型でインスタンス化できます。完全な非述語性をサポートするシステムの例として、System Fがあります。System F では、インスタンス化が可能です。あらゆるタイプにおいて、それ自体も含めて。
Leivant のランクの概念は、適切な簡単な置換によって量化子以外の記号にも一般化できます。たとえば、交差型(のコンストラクタ) に適用できます。ただし、結果として得られるランクベースの型階層は、異なる特性を持つ可能性があります。たとえば、ランク 3 以上のシステム F の型推論は (上記で詳述したように) 決定不能のままですが、交差型の場合、型推論はすべての有限ランクで決定可能です。[ 13 ]
1985年、Luca CardelliとPeter Wegnerは、型パラメータに制約を設けることの利点を認識しました。 [ 14 ]多くの操作はデータ型に関する知識を必要としますが、それ以外はパラメータに基づいて動作させることができます。たとえば、項目がリストに含まれているかどうかを確認するには、項目の等価性を比較する必要があります。Standard MLでは、 ''aの形式の型パラメータは等価性演算が利用できるように制限されているため、関数は型''a × ''a list → boolとなり、''aは等価性が定義された型のみになります。Haskellでは、型が型クラスに属することを要求することで制約が実現されます。したがって、同じ関数は型''a × ''a list → boolとなります。Haskell では、パラメータ多相性をサポートするほとんどのオブジェクト指向プログラミング言語では、パラメータを特定の型のサブタイプに制約することができます (サブタイプ多相性とジェネリックプログラミングの記事を参照)。
クラス宣言の区別された型変数 (セクション 4.3.1) を除き、Haskell の型式の型変数はすべて全称量化されていると想定されています。全称量化のための明示的な構文はありません。
{{citation}}: CS1 maint: 場所の発行元が見つかりません (リンク)。