Module expressions are the module-level equivalent of value expressions: they evaluate to modules, thus providing implementations for the specifications expressed in module types.
module-expr: module-path |struct
{definition [;;
]}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
class-definition {and
class-definition}end
|module
module-name {(
module-name:
module-type)
} [:
module-type]=
module-expr |module
type
modtype-name=
module-type |open
module-path
The expression module-path evaluates to the module bound to the name module-path.
The expression (
module-expr )
evaluates to the same module as
module-expr.
The expression (
module-expr :
module-type )
checks that the
type of module-expr is a subtype of module-type, that is, that all
components specified in module-type are implemented in
module-expr, and their implementation meets the requirements given
in module-type. In other terms, it checks that the implementation
module-expr meets the type specification module-type. The whole
expression evaluates to the same module as module-expr, except that
all components not specified in module-type are hidden and can no
longer be accessed.
Structures struct
...end
are collections of definitions for
value names, type names, exceptions, module names and module type
names. The definitions are evaluated in the order in which they appear
in the structure. The scope of the bindings performed by the
definitions extend to the end of the structure. As a consequence, a
definition may refer to names bound by earlier definitions in the same
structure.
For compatibility with toplevel phrases (chapter 8)
and with Caml Light, an optional ;; is allowed after each
definition in a structure. The ;; has no semantic meaning. Also for
compatibility, expr ;;
is allowed as a component of a structure,
meaning let
_
=
expr, i.e. evaluate expr for its side-effects.
A value definition let
[rec
] let-binding {and
let-binding}
bind value names in the same way as a let
...in
... expression
(see section 5.8). The value names appearing in the
left-hand sides of the bindings are bound to the corresponding values
in the right-hand sides.
A value definition external
value-name :
typexpr =
external-declaration
implements value-name as the external function specified in
external-declaration (see chapter 15).
A definition of one or several type components is written
type
typedef {and
typedef} and consists of a sequence
of mutually recursive definitions of type names.
Exceptions are defined with the syntax exception
constr-decl.
The class
keyword introduces one or several mutually recursive
class definitions, as described in section 5.10.
The basic form for defining a module component is
module
module-name =
module-expr, which evaluates module-expr and binds
the result to the name module-name.
One can write
instead ofmodule
module-name:
module-type=
module-expr
Another derived form ismodule
module-name=
(
module-expr:
module-type)
.
which is equivalent tomodule
module-name(
name1:
module-type1)
...(
namen:
module-typen)
=
module-expr
module
module-name=
functor
(
name1:
module-type1)
->
...->
module-expr
A definition for a module type is written
module
type
modtype-name =
module-type.
It binds the name modtype-name to the module type denoted by the
expression module-type.
The expression open
module-path in a structure does not define any
components nor perform any bindings. It simply affects the parsing of
the following items of the structure, allowing components of the
module denoted by module-path to be referred to by their simple names
name instead of path accesses module-path .
name. The scope of
the open stops at the end of the structure expression.
The expression functor
(
module-name :
module-type )
->
module-expr evaluates to a functor that takes as argument modules of
the type module-type1, binds module-name to these modules,
evaluates module-expr in the extended environment, and returns the
resulting modules as results. No restrictions are placed on the type of the
functor argument; in particular, a functor may take another functor as
argument (``higher-order'' functor).
The expression module-expr1 (
module-expr2 )
evaluates
module-expr1 to a functor and module-expr2 to a module, and
applies the former to the latter. The type of module-expr2 must
match the type expected for the arguments of the functor module-expr1.