7.11 Module expressions (module implementations)
Module expressions are the module-level equivalent of valueexpressions: they evaluate to modules, thus providing implementationsfor the specifications expressed in module types.
|
See also the following language extensions:recursive modules,first-class modules,overriding in open statements,attributes,extension nodes andgenerative functors.
7.11.1 Simple module expressions
The expression module-path evaluates to the module bound to the namemodule-path.
The expression (module-expr) evaluates to the same module asmodule-expr.
The expression (module-expr: module-type) checks that thetype of module-expr is a subtype of module-type, that is, that allcomponents specified in module-type are implemented inmodule-expr, and their implementation meets the requirements givenin module-type. In other terms, it checks that the implementationmodule-expr meets the type specification module-type. The wholeexpression evaluates to the same module as module-expr, except thatall components not specified in module-type are hidden and can nolonger be accessed.
7.11.2 Structures
Structures struct … end are collections of definitions forvalue names, type names, exceptions, module names and module typenames. The definitions are evaluated in the order in which they appearin the structure. The scopes of the bindings performed by thedefinitions extend to the end of the structure. As a consequence, adefinition may refer to names bound by earlier definitions in the samestructure.
For compatibility with toplevel phrases (chapter 10),optional ;; are allowed after and before each definition in a structure. These;; have no semantic meanings. Similarly, an expr preceded by ;; is allowed asa component of a structure. It is equivalent to let_=expr, i.e. expr isevaluated for its side-effects but is not bound to any identifier. If expr isthe first component of a structure, the preceding ;; can be omitted.
Value definitions
A value definition let [rec] let-binding { andlet-binding }bind value names in the same way as a let … in … expression(see section 7.7.2). The value names appearing in theleft-hand sides of the bindings are bound to the corresponding valuesin the right-hand sides.
A value definition externalvalue-name: typexpr= external-declarationimplements value-name as the external function specified inexternal-declaration (see chapter 19).
Type definitions
A definition of one or several type components is writtentypetypedef { andtypedef } and consists of a sequenceof mutually recursive definitions of type names.
Exception definitions
Exceptions are defined with the syntax exceptionconstr-declor exceptionconstr-name= constr.
Class definitions
A definition of one or several classes is written classclass-binding { andclass-binding } and consists of a sequence ofmutually recursive definitions of class names. Class definitions aredescribed more precisely in section 7.9.3.
Class type definitions
A definition of one or several classes is writtenclasstypeclasstype-def { andclasstype-def } and consists ofa sequence of mutually recursive definitions of class type names.Class type definitions are described more precisely insection 7.9.5.
Module definitions
The basic form for defining a module component ismodulemodule-name= module-expr, which evaluates module-expr and bindsthe result to the name module-name.
One can write
modulemodule-name: module-type= module-expr
instead of
modulemodule-name=( module-expr: module-type).
Another derived form is
modulemodule-name( name1: module-type1) …( namen: module-typen)= module-expr
which is equivalent to
modulemodule-name=functor( name1: module-type1)-> …-> module-expr
Module type definitions
A definition for a module type is writtenmoduletypemodtype-name= module-type.It binds the name modtype-name to the module type denoted by theexpression module-type.
Opening a module path
The expression openmodule-path in a structure does not define anycomponents nor perform any bindings. It simply affects the parsing ofthe following items of the structure, allowing components of themodule denoted by module-path to be referred to by their simple namesname instead of path accesses module-path. name. The scope ofthe open stops at the end of the structure expression.
Including the components of another structure
The expression includemodule-expr in a structure re-exports inthe current structure all definitions of the structure denoted bymodule-expr. For instance, if you define a module S as below
module S = struct type t = int let x = 2 end
defining the module B as
module B = struct include S let y = (x + 1 : t) end
is equivalent to defining it as
module B = struct type t = S.t let x = S.x let y = (x + 1 : t) end
The difference between open and include is that opensimply provides short names for the components of the openedstructure, without defining any components of the current structure,while include also adds definitions for the components of theincluded structure.
7.11.3 Functors
Functor definition
The expression functor(module-name: module-type)-> module-expr evaluates to a functor that takes as argument modules ofthe type module-type1, binds module-name to these modules,evaluates module-expr in the extended environment, and returns theresulting modules as results. No restrictions are placed on the type of thefunctor argument; in particular, a functor may take another functor asargument (“higher-order” functor).
Functor application
The expression module-expr1( module-expr2) evaluatesmodule-expr1 to a functor and module-expr2 to a module, andapplies the former to the latter. The type of module-expr2 mustmatch the type expected for the arguments of the functor module-expr1.