Module types are the modulelevel equivalent of type expressions: they specify the general shape and type properties of modules.


The expression modtypepath is equivalent to the module type bound to the name modtypepath. The expression ( moduletype ) denotes the same type as moduletype.
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.
An optional ;; is allowed after each specification in a signature. It serves as a syntactic separator with no semantic meaning.
A specification of a value component in a signature is written val valuename : typexpr, where valuename is the name of the value and typexpr its expected type.
The form external valuename : typexpr = externaldeclaration is similar, except that it requires in addition the name to be implemented as the external function specified in externaldeclaration (see chapter 19).
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 = typexpr and an optional type representation = constrdecl … or = { fielddecl … }. 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:
The specification exception constrdecl 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 specification of one or several classes in a signature is written class classspec { and classspec } and consists of a sequence of mutually recursive definitions of class names.
Class specifications are described more precisely in section 6.9.4.
A specification of one or several classe types in a signature is written class type classtypedef { and classtypedef } and consists of a sequence of mutually recursive definitions of class type names. Class type specifications are described more precisely in section 6.9.5.
A specification of a module component in a signature is written module modulename : moduletype, where modulename is the name of the module component and moduletype 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 of
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 modtypename allows the name modtypename 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 modtypename = moduletype requires the name modtypename to be implemented by the module type moduletype in a matching signature, but makes the equality between modtypename and moduletype apparent to all users of the signature.
The expression open modulepath 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 modulepath to be referred to by their simple names name instead of path accesses modulepath . name. The scope of the open stops at the end of the signature expression.
The expression include moduletype in a signature performs textual inclusion of the components of the signature denoted by moduletype. It behaves as if the components of the included signature were copied at the location of the include. The moduletype argument must refer to a module type that is a signature, not a functor type.
The module type expression functor ( modulename : moduletype_{1} ) > moduletype_{2} is the type of functors (functions from modules to modules) that take as argument a module of type moduletype_{1} and return as result a module of type moduletype_{2}. The module type moduletype_{2} can use the name modulename to refer to type components of the actual argument of the functor. If the type moduletype_{2} does not depend on type components of modulename, the module type expression can be simplified with the alternative short syntax moduletype_{1} > moduletype_{2} . No restrictions are placed on the type of the functor argument; in particular, a functor may take another functor as argument (“higherorder” functor).
Assuming moduletype denotes a signature, the expression moduletype with modconstraint { and modconstraint } 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 [typeparameters] typeconstr = typexpr adds the type equation = typexpr to the specification of the type component named typeconstr of the constrained signature. The constraint module modulepath = extendedmodulepath adds type equations to all type components of the substructure denoted by modulepath, making them equivalent to the corresponding type components of the structure denoted by extendedmodulepath.
For instance, if the module type name S is bound to the signature
sig type t module M: (sig type u end) end
then S with type t=int denotes the signature
sig type t=int module M: (sig type u end) end
and S with module M = N denotes the signature
sig type t module M: (sig type u=N.u end) end
A functor taking two arguments of type S that share their t component is written
functor (A: S) (B: S with type t = A.t) ...
Constraints are added left to right. After each constraint has been applied, the resulting signature must be a subtype of the signature before the constraint was applied. Thus, the with operator can only add information on the type components of a signature, but never remove information.