This extension makes it possible to open any module expression in
module structures and expressions. A similar mechanism is also available
inside module types, but only for extended module paths (e.g. F(X).G(Y)).
For instance, a module can be constrained when opened with
module M = structlet x = 0 let hidden = 1 endopen (M:sigval x: int end)
let y = hidden
Error: Unbound value hidden
Another possibility is to immediately open the result of a functor application
let sort (type x) (x:x list) =
letopen Set.Make(structtype t = x let compare=compare end) in
elements (of_list x)
val sort : 'x list -> 'x list = <fun>
Going further, this construction can introduce local components inside a
structure,
module M = structlet x = 0
open! structlet x = 0
let y = 1
endlet w = x + y
end
module M : sigval x : int val w : int end
One important restriction is that types introduced by openstruct ...
end cannot appear in the signature of the enclosing structure, unless they
are defined equal to some non-local type.
So:
module M = structopenstructtype 'a t = 'a option = None | Some of 'a endlet x : int t = Some 1
end
module M : sigval x : int option end
is OK, but:
module M = structopen struct type t = A endlet x = A
end
Error: The type t/4694 introduced by this open appears in the signature
File "exten.etex", line 3, characters 6-7:
The value x has no valid type if t/4694 is hidden
is not because x cannot be given any type other than t, which only exists
locally. Although the above would be OK if x too was local:
module M: sigend = structopenstructtype t = A
end
…
openstructlet x = A end
…
end
module M : sigend
Inside signatures, extended opens are limited to extended module paths,
moduletype S = sigmodule F: sigend -> sigtype t endmodule X: sigendopen F(X)
val f: t
end
moduletype S =
sigmodule F : sigend -> sigtype t endmodule X : sigendval f : F(X).t
end
and not
open struct type t = int end
In those situations, local substitutions(see 8.7.2)
can be used instead.
Beware that this extension is not available inside class definitions: