Module types are the module-level equivalent of type expressions: they specify the general shape and type properties of modules.
module-type: modtype-path |sig
{specification [;;
]}end
|functor
(
module-name:
module-type)
->
module-type | module-typewith
constraint {and
constraint} |(
module-type)
specification:val
value-name:
typexpr |external
value-name:
typexpr=
external-declaration | type-definition | exception-definition |class
class-type {and
class-type}end
|module
module-name:
module-type |module
module-name {(
module-name:
module-type)
}:
module-type |module
type
modtype-name |module
type
modtype-name=
module-type |open
module-path constraint:type
[type-parameters] typeconstr=
typexp |module
module-path=
extended-module-path
The expression modtype-path is equivalent to the module type bound
to the name modtype-path.
The expression (
module-type )
denotes the same type as
module-type.
Signatures are type specifications for structures. Signatures
sig
...end
are collections of type specifications for value
names, type names, exceptions, module names and module type names. A
structure will match a signature if the structure provides definitions
(implementations) for all the names specified in the signature (and
possibly more), and these definitions meet the type requirements given
in the signature.
For compatibility with Caml Light, an optional ;; is allowed after each specification in a signature. The ;; has no semantic meaning.
A specification of a value component in a signature is written
val
value-name :
typexpr, where value-name is the name of the
value and typexpr its expected type.
The form external
value-name :
typexpr =
external-declaration
is similar, except that it requires in addition the name to be
implemented as the external function specified in external-declaration
(see chapter 15).
A specification of one or several type components in a signature is
written type
typedef {and
typedef} and consists of a sequence
of mutually recursive definitions of type names.
Each type definition in the signature specifies an optional type
equation =
typexp and an optional type representation
=
constr-decl... or =
{
label-decl...}
.
The implementation of the type name in a matching structure must
be compatible with the type expression specified in the equation (if
given), and have the specified representation (if given). Conversely,
users of that signature will be able to rely on the type equation
or type representation, if given. More precisely, we have the
following four situations:
=
typexp, no representation.
The specification exception
constr-decl in a signature requires the
matching structure to provide an exception with the name and arguments
specified in the definition, and makes the exception available to all
users of the structure.
A class specification is composed of one or several mutually recursive class types, as described in section 5.10.
A specification of a module component in a signature is written
module
module-name :
module-type, where module-name is the
name of the module component and module-type its expected type.
Modules can be nested arbitrarily; in particular, functors can appear
as components of structures and functor types as components of
signatures.
For specifying a module component that is a functor, one may write
instead ofmodule
module-name(
name1:
module-type1)
...(
namen:
module-typen)
:
module-type
module
module-name:
functor
(
name1:
module-type1)
->
...->
module-type
A module type component of a signature can be specified either as a manifest module type or as an abstract module type.
An abstract module type specification
module
type
modtype-name allows the name modtype-name to be
implemented by any module type in a matching signature, but hides the
implementation of the module type to all users of the signature.
A manifest module type specification
module
type
modtype-name =
module-type
requires the name modtype-name to be implemented by the module type
module-type in a matching signature, but makes the equality between
modtype-name and module-type apparent to all users of the signature.
The expression open
module-path in a signature does not specify
any components. It simply affects the parsing of the following items
of the signature, 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 signature expression.
The module type expression
functor
(
module-name :
module-type1 )
->
module-type2
is the type of functors (functions from modules to modules) that take
as argument a module of type module-type1 and return as result a
module of type module-type2. The module type module-type2 can
use the name module-name to refer to type components of the actual
argument of the functor. No restrictions are placed on the type of the
functor argument; in particular, a functor may take another functor as
argument (``higher-order'' functor).
Assuming module-type denotes a signature, the expression
module-type with
constraint {and
constraint} denotes the same
signature where type equations have been added to some of the type
specifications, as described by the constraints following the with
keyword. The constraint type
[type-parameters] typeconstr =
typexp
adds the type equation =
typexp to the specification of the type
component named typeconstr of the constrained signature.
The constraint module
module-path =
extended-module-path adds
type equations to all type components of the sub-structure denoted by
module-path, making them equivalent to the corresponding type
components of the structure denoted by extended-module-path.
For instance, if the module type name S is bound to the signature
sig type t module M: (sig type u end) endthen S with type t=int denotes the signature
sig type t=int module M: (sig type u end) endand S with module M = N denotes the signature
sig type t module M: (sig type u=N.u end) endA functor taking two arguments of type S that share their t component is written
functor (A: S) (B: S with type t = A.t) ...