6.11 モジュール式

6.11.1. 単純なモジュール式
6.11.2. ストラクチャ
6.11.3. ファンクタ

モジュール式はモジュールにおける値式で、モジュールに評価されます。 モジュール式はモジュール型で表現された仕様に対する実装です。

module-expr ::= module-path
| struct { definition [ ;; ] || expr ;; } end
| functor ( module-name : module-type ) -> module-expr
| module-expr ( module-expr )
| ( module-expr )
| ( module-expr : module-type )
definition ::= let [ rec ] let-binding { and let-binding }
| external value-name : typexpr = external-declaration
| type-definition
| exception-definition
| class-definition
| classtype-definition
| module module-name { ( module-name : module-type ) } [ : module-type ] = module-expr
| module type modtype-name = module-type
| open module-path
| include module-expr

6.11.1 単純なモジュール式

module-path はその名前に束縛されたモジュールに評価されます。

(module-expr)module-expr と同じモジュールに評価されます。

(module-expr : module-type) は、 module-expr の型が module-type の部分型であるかどうか、すなわち、 module-type で規定された要素がすべて module-expr で実装されてい、その実装が module-type の要求に合致しているかをチェックします。 式全体は module-expr と同じモジュールに評価されますが、 module-type に指定されていない要素はすべて隠蔽され、アクセスできなくなります。

6.11.2 ストラクチャ

ストラクチャ struct ... end は、値の名前、型名、例外、モジュール名、モジュール型の名前に対する定義を集めたものです。 各定義はストラクチャ内に現れた順に評価されます。 各定義により確立される束縛のスコープはストラクチャ全体にまで拡大されます。 そのため、ある定義で、同一のストラクチャ内で先に定義した名前を参照することができます。

トップレベルや Caml Lightとの互換性のために、定義の後ろには ;; を付けられます。 ;; に特別な意味はありません。 また、さらに互換性のために、構成要素として expr ;; と書くこともできます。 これは let _ = expr を意味し、 expr は副作用のために評価されます。 このときの ;; は省略できません。

値の定義

値の定義 let [rec] let-binding { and let-binding } は let ... in ... 式(「局所定義 」参照)と同じく値の名前を束縛します。 束縛の左辺に現れる名前は対応する右辺の値に束縛されます。

external value-name : typexpr = external-declaration の値定義は、 value-nameexternal-declaration で指定された外部関数として実装[10]します。

型定義

type typedef { and typedef } として、相互再帰的な型の名前の定義を書くことができます。

例外定義

例外は exception constr-decl、または exception constr-name = constr として定義します。

クラス定義

class class-binding { and class-binding } として、相互再帰的なクラスの名前から成る定義を書くことができます。 クラス定義については 6.9.3 節「クラス定義 」により正確に説明されています。

クラス型定義

class type classtype-def { and classtype-def } として、相互再帰的なクラス型の名前の定義からなるクラス型の定義を書くことができます。クラス型の定義は 6.9.5 節「クラス型定義 」により正確に説明されています。

モジュール定義

モジュール要素の定義の構文の基本形は module module-name = module-expr で、 module-expr を評価し、その結果を module-name に束縛します。

と書く代わりに

と書くこともできます。 また、

module module-name ( name1 module-type1) ... (namen : module-typen) = module-expr

module module-name = functor (name1 : module-type1) -> ... -> module-expr

と等価です。

モジュール型の定義

モジュール型の定義は module type modtype-name = module-type と書き、 module-type の表すモジュール型に modtype-name を束縛します。

モジュールパスの open

ストラクチャ内で open module-path としても何の要素も定義されず、名前も束縛されません。 この構文はストラクチャ内の後続する要素の構文解析に影響を与え、 module-path の表すモジュールの構成要素が、 module-path 経由ではなく、単純名で参照できるようにする効果しかありません。 open のスコープはストラクチャ式の末尾で終了します。

他のストラクチャからの要素の取り込み

モジュール中で include module-expr とすると、 module-expr の表すストラクチャ内のすべての定義が現在のストラクチャに再エクスポートされます。 例えば、識別子 S が次のモジュールに束縛されているとき、

struct type t = int  let x = 2 end

次のモジュール式

struct include S  let y = (x + 1 : t) end

は下のモジュール式と等価になります。

struct type t = int  let x = 2  let y = (x + 1 : t) end

openinclude の違いは、 open が単純に、 open されたストラクチャの構成要素へ短かい名前でアクセスできるようにするだけで、現在のストラクチャには何の要素も定義しないのに対し、 includeinclude されたストラクチャの要素の定義を現在のストラクチャに追加するということです。

6.11.3 ファンクタ

ファンクタ定義

functor ( module-name : module-type) -> module-exprmodule-type1 型のモジュールを引数に取るファンクタに評価されます。 module-exprmodule-name の束縛された環境で評価され、その結果のモジュールを返します。 ファンクタの引数の型には何の制約もなく、特に、ファンクタが別のファンクタを引数に取ることもできます(高階ファンクタ)。

ファンクタ適用

module-expr1 (module-expr2)module-expr1 がファンクタに評価され、 module-expr2 がモジュールに評価され、そのファンクタをモジュールに適用します。 module-expr2 の型は module-expr1 の引数型として期待される型に適合しなければなりません。



[10] 原文 implements。定義、あるいは束縛か。