6.4 型式

6.4.1. 型変数
6.4.2. 括弧付きの型
6.4.3. 関数型
6.4.4. タプル型
6.4.5. 構成された型
6.4.6. エイリアス型・再帰型
6.4.7. 多相バリアント型
6.4.8. オブジェクト型
6.4.9. # 型
6.4.10. バリアント型とレコード型
typexpr ::= ' ident
| _
| ( typexpr )
| [ [ ? ] label-name : ] typexpr -> typexpr
| typexpr { * typexpr }+
| typeconstr
| typexpr typeconstr
| ( typexpr { , typexpr } ) typeconstr
| typexpr as ' ident
| polymorphic-variant-type
| < [ .. ] >
| < method-type { ; method-type } [ ; .. ] >
| # class-path
| typexpr # class-path
| ( typexpr { , typexpr } ) # class-path
poly-typexpr ::= typexpr
| { ' ident }+ . typexpr
method-type ::= method-name : poly-typexpr

下のテーブルに、演算子と閉じていない型構成子の相対的な優先順位と結合性を示します。優先順位のものが先に来ます。

演算子結合性
型構成子の適用-
*-
->
as-

型式は、パターンや式における型制約と同じく、データの型の定義における型を表します。

6.4.1 型変数

型式 'ident は、ident という名前の型変数を意味します。 型式 _ は無名の型変数を意味します。 型変数は、型定義においては型パラメータの名前であり、型制約においてはその型制約を満たすあらゆる型としてインスタンス化できる不特定の型を意味します。 通常、名前付き型変数のスコープは、その型変数を含む定義全体になります。 このスコープから外れると、型変数の名前は一般化されます。 無名の型変数にはこのような制約はありません。 次のような場合、名前付き型変数のスコープはその型変数の出現した型式内に限定されます。 1) 全称(陽に多相)の型変数、 2) パブリックメソッドの型指定にのみ現れる型変数(「メソッドの仕様 」 に書かれているように、これは全称の型変数になります)、 3) 別名として使われている型変数で、それを囲んだ定義において不正となるようなもの(つまり、別名の型変数が全称の型変数やローカルに定義された型を含む場合)。

6.4.2 括弧付きの型

型式 ( typexpr )typexpr と同じ型を示します。

6.4.3 関数型

型式 typexpr1 -> typexpr2 は型typexpr1 の引数を取り、型 typexpr2 を返す関数の型を示します。

型式 ~ label-name : typexpr1 -> typexpr2 も同じ関数型を示しますが、その引数は label によってラベルづけされます。

型式 ? label-name : typexpr1 -> typexpr2 は省略可能なラベルつき引数 typexpr1 を受け取り型 typexpr2 を返す関数を示します。つまり、この関数の実際の型は typexpr1 option -> typexpr2 となります。

6.4.4 タプル型

型式 typexpr1 * ... * typexprn はタプルの型を示し、その組の要素はそれぞれ typexpr1, ..., typexprn です。

6.4.5 構成された型

パラメータを持たない型構成子は上では typeconstr と表記されていますが、これは型式です。

型式 typexpr typeconstrtypeconstr ひとつのパラメータを与えられた型構成子であり、単項型構成子 typeconstr の型 typexpr への適用を示します。

型式 ( typexpr1, ..., typexprn ) typeconstrn 個のパラメータを与えられた型構成子であり、 n 項型構成子 typeconstrtypexpr1 から typexprn への適用を示します。

6.4.6 エイリアス型・再帰型

型式 typexpr as ' ident は型 typexpr と同じ型を示し、なおかつ typexpr および残りの部分において型変数 identtypexpr に束縛します。 一般に別名のスコープは名前付きの型変数と同じで、それを囲む定義全体を含みます。型変数 identtypexpr の中に実際に存在した場合には再帰的な型が生成されます。オブジェクトや多相バリアント型構成子を含まない再帰パスが存在する再帰型は、 -rectypes モードが選択されている場合を除いて棄却されます。

もし ' ident が明らかに多相型を表していて、 typexpr がオブジェクトまたは多相バリアント型を表していた場合、 typexpr の列変数は ' ident によって捕捉され量化されます。

6.4.7 多相バリアント型

polymorphic-variant-type ::= [ [ | ] tag-spec { | tag-spec } ]
| [> [ tag-spec ] { | tag-spec } ]
| [< [ | ] tag-spec-full { | tag-spec-full } [ > { ` tag-name }+ ] ]
tag-spec ::= ` tag-name [ of typexpr ]
| typexpr
tag-spec-full ::= ` tag-name [ of typexpr ] { & typexpr }
| typexpr

多相バリアント型は多相バリアントによって取ることのできる値を表します。

最初のケースは正確なバリアント型です。可能なタグとそれに対応する型がすべて既知で、すべて存在しています。その構造は完全に既知です。

二番目のケースは開いたバリアント型で、多相バリアント値を記述します。 これは、現れうるすべてのタグとそれに対応する型をすべて与えます。この型は、与えられたタグよりも多くのタグを含むバリアント型とも互換性があります。これの特殊な場合として不明型があり、一切のタグを定義しないもので、あらゆるバリアント型と互換性があります。

三番目のケースは閉じたバリアント型です。これは全ての可能なタグと関連した型、それから値の中に現れる可能性のあるタグについての情報を与えます。上記の正確なバリアント型は、すべての可能なタグが潜在的に存在する閉じたバリアント型の略記に過ぎません。

これら3つのケース全てで、タグは `tag-name [...] の形式で直接指定されるか、型式によって間接的に表現されます。最後のケースでは、型式は正確なバリアント型に展開されなくてはなりません。そのタグ指定はその場所に展開されます。

バリアントタグの完全な指定は正確でない閉じた型でのみ利用されます。これは引数の型をすべて結合した型として考えることができ、仕様として列挙された型すべてを取ることを期待しています。

このような結合制約は充足不能であるかもしれません。そのような場合、対応するタグはこの型の値として利用できないことがあります。これは、これによってその型全体が妥当ではなくなるということではなく、他の利用可能なタグを依然として使うことができます。

6.4.8 オブジェクト型

オブジェクト型 < method-type { ; method-type } > はメソッド型のレコードです。

それぞれのメソッドは陽な多相型 { ' ident }+ . typexpr を持つかもしれません。陽な多相変数は局所的なスコープを持ち、同じ位置に多相変数を持つ等価な型とだけ同一化することができます。

型 { ' ident }+ < method-type { ; method-type } .. > は、 method-type1, ..., method-typen で表されたメソッドと関連付けられた型を持つオブジェクトの型です。他のメソッドが存在する可能性は .. で表現されています。この省略表現は実際には特殊な種類の型変数で(列変数 — row variable と呼ばれます)、他の任意個のメソッドを意味します。

6.4.9 # 型

# class-path は特殊な種類の略記です。この略記はクラス class-path の子クラスに属するあらゆるオブジェクトの型を単一化したものです。この型は、型変数(子クラスに追加されているかもしれないメソッドを表現する省略記号)を隠蔽するよう、特別扱いされます。特に、省略記号がインスタンス化するとこの型は消滅します。個々の型式 # class-path は新しい型変数を定義するので、型 # class-path -> # class-path と型 ( # class-path as ' ident ) -> ' ident は通常の場合、同一ではありません。

多相バリアント型に対する #-型の利用は推奨されません。もし t が正確なバリアント型なら #t[< t] に変換され、 #t[> `tag1 ...`tagk][< t > `tag1 ...`tagk] に翻訳されます。

6.4.10 バリアント型とレコード型

バリアント型としてもレコード型としても表現(定義)されない型式は存在しません。なぜならこれらは常に名前が付いてい、利用に先立って定義され、名前によって参照されているからです。型の定義は 6.8.1 節「型定義 」で説明されています。