型定義では型コンストラクタを、バリアント型やレコード型、型略記、抽象データ型といったデータ型に束縛します。 また、定義に対応する値コンストラクタや、レコードのフィールドも束縛します。
type-definition | ::= | type typedef { and typedef } |
typedef | ::= | [ type-params ] typeconstr-name [ type-information ] |
type-information | ::= | [ type-equation ] [ type-representation ] { type-constraint } |
type-equation | ::= | = typexpr |
type-representation | ::= | = constr-decl { | constr-decl } |
| | = { field-decl { ; field-decl } } | |
type-params | ::= | type-param |
| | ( type-param { , type-param } ) | |
type-param | ::= | ' ident |
| | + ' ident | |
| | - ' ident | |
constr-decl | ::= | constr-name |
| | constr-name of typexpr { * typexpr } | |
field-decl | ::= | field-name poly-typexpr |
| | mutable field-name : poly-typexpr | |
type-constraint | ::= | constraint ' ident = typexpr |
型定義は予約語 type
で始まり、ひとつ以上の単純な定義から構成されます。
単純な定義は相互に再帰してもよく、各々を and
で区切ります。
単純な定義ではそれぞれ型構成子をひとつ定義します。
単純な定義は小文字の識別子から成り、その前にひとつ以上の型パラメータを指定することができ、後に型等式、型表現、制約節をそれぞれ続けることができます。 識別子は定義される型構成子の名前になります。
型パラメータは、一引数の型構成子に対する単一の型変数 ' ident か、複数のパラメータを取る型構成子に対する型変数のリスト ('ident1, ..., identn
) のいずれかです。
型パラメータの前にはそれぞれ変位制約 + (または -)をつけ、その型パラメータが共変(または反変)であることを示すことができます。
これらの型変数は最終的に変位制約による制約を受けつつ、型定義の右辺の型式の中に現れることができます。
すなわち、共変パラメータは関数の矢印の右側(より正確に言えば、奇数番目の矢印の右枝)に現れることができ、反変パラメータは左側(より正確に言えば、偶数番目の矢印の左枝)に現れることができます。
型に表現か等式があり、パラメータが自由である(すなわち、構成される型への型制約で束縛されていない)場合、変位制約はチェックされますが、部分型派生の場合などにはそのパラメータに対しては推論された変位指定が使われます。
推論されたも変位指定の方がより適切なこともあるでしょう。
それ以外の場合(抽象型の場合や、自由な型変数がない場合)には、変位指定を明示しなければならず、変位指定がなければパラメータは不変になります。
型等式 = typexpr を指定すると、定義される型は等号の右辺の型式 typexpr と等価になります。 型付けにおいて一方で他方を置き換えることができるようになります。 型等式が与えられなかった場合には、新たな型が生成され、定義された型は他のいずれの型とも互換性のない型になります。
型表現は、定義される型が表現するデータ構造を表し、対応する構成子のリストか(バリアント型の場合)、対応するフィールドのリスト(レコード型の場合)を指定します。 型表現が与えられていない場合、型等式で与えられた型の構造以外何も仮定されません。
型表現 = constr-decl { | constr-decl } はバリアント型を表します。
構成子宣言 constr-decl1, ..., constr-decln
はこのバリアント型に関連づけられた構成子を表します。
構成子宣言 constr-name of typexpr1, ..., typexprn
は constr-name を、型 typexpr1 ... typexprn
を引数の型として持つ非定数コンストラクタとして宣言します。
構成子の名前はキャピタライズされていなければなりません。
型表現 = { field-decl { ; field-decl } } はレコード型を表します。
フィールド宣言 field-decl1, ..., field-decln
はこのレコード型に関連づけられたフィールドを表します。
フィールド宣言 field-name : poly-typexpr は field-name を poly-typexpr 型のフィールド[4]として宣言します。
フィールド宣言 mutable field-name : poly-typexpr も同様に振舞いますが、加えて、このフィールドに物理的変更を許します。
変更不能なフィールドは共変ですが、変更可能なフィールドは共変でも反変でもありません。
変更可能なフィールドにも変更不能なフィールドにも多相型を指定することができます。
フィールドの内容の多相性はレコード値が作成されたり変更されるたびに静的にチェックされます。
フィールドから取り出された値は型変数をインスタンス化した型になることがあります。
型定義の構成要素である型等式と型表現は独立に組み合わせることができ、典型的には次のよっつの状況があります。
モジュールシグネチャ内に現れた場合、この定義は型構成子について、パラメータの個数以外何も指定しない。 表現は隠蔽され、他のいずれの型にも適合しないものと仮定される。
型構成子を等号の右辺の型式の略記と定義する。
新たな型構成子を生成し、対応する構成子かフィールドを定義する。 これらを使ってこの型の値の直接作成/アクセスを行なう。
この場合、型構成子は等式に与えられた型式の略記として定義されるが、それに加えて表現部分に与えられた構成子やフィールドが定義された型構成子に追加される。
等式部分の型式は型表現に一致しなければなりません。 すなわち、同一の種類(レコードかバリアント)であり、まったく同じ構成子ないしフィールドを、同一の順序で、同一の引数を持たなければなりません。
型パラメータとして現れる型変数には +
または -
を前置して、型構成子がそのパラメータについて共変か反変かを表すことができます。
この変位情報は :> 型変換( 6.7.6 節「型変換 」参照)の妥当性を検査するとき、部分型関係を決定するのに使われます。
例えば、 type +'a t
は t
をそのパラメータに対して共変な抽象型として宣言しています。
これは、 τ
が型 σ
の部分型であるとき、
τ t
が σ t
の部分型になるということです。
同様に、 -'a t
は t
をそのパラメータに対して反変な抽象型として宣言します。
τ
が σ
の部分型であるとき、
σ t
は τ t
の部分型になります。
+
、 -
の変位アノテーションがない場合、型構成子は、対応するパラメータに対して不変であるものとされます。
このとき、抽象型宣言 'a t
は、 τ
が σ
の部分型であっても、 τ t
は σ t
の上位型にも部分型にもなりません。
+
と -
による変位アノテーションは抽象型の場合だけ必要です。
略記法として、バリアント型とレコード型では、型構成子の変位性は定義から推論され、変位アノテーションは定義への適合性についてだけ検査されます。
constraint ' ident = typexpr 構文を使うと型パラメータを指定することができます。 型パラメータ ident に対応する実型引数は typexpr のインスタンスになります(より正確に言うと、 ident と typexpr が単一化されます)。 typexpr 中の型変数は型等式と型宣言中で使うことができます。
exception-definition | ::= | exception constr-name [ of typexpr { * typexpr } ] |
| | exception constr-name = constr |
例外定義は組込みの例外値のバリアント型 exn に新しい構成子を追加します。 構成子はバリアント型の定義と同様に定義します。
exception constr-name [of typexpr { * typexpr }] は、システム中の他のすべての例外と異なる、新しい例外を生成します。 constr-name = constr は既存の例外に別名を与えます。