8.23 Generalized open statements

(Introduced in 4.08)

definition::=
open module-expr
open! module-expr
specification::=
open extended-module-path
open! extended-module-path
expr::=
let open module-expr in expr
let open! module-expr in expr

This extension makes it possible to open any module expression inmodule structures and expressions. A similar mechanism is also availableinside module types, but only for extended module paths (e.g. F(X).G(Y)).

For instance, a module can be constrained when opened with

  1. module M = struct let x = 0 let hidden = 1 end
  2. open (M:sig val x: int end)
  3. let y = hidden
  4.  
  5. Error: Unbound value hidden

Another possibility is to immediately open the result of a functor application

  1. let sort (type x) (x:x list) =
  2. let open Set.Make(struct type t = x let compare=compare end) in
  3. elements (of_list x)
  4. val sort : 'a list -> 'a list = <fun>

Going further, this construction can introduce local components inside astructure,

  1. module M = struct
  2. let x = 0
  3. open! struct
  4. let x = 0
  5. let y = 1
  6. end
  7. let w = x + y
  8. end
  9. module M : sig val 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 theyare defined equal to some non-local type.So:

  1. module M = struct
  2. open struct type 'a t = 'a option = None | Some of 'a end
  3. let x : int t = Some 1
  4. end
  5. module M : sig val x : int option end

is OK, but:

  1. module M = struct
  2. open struct type t = A end
  3. let x = A
  4. end
  5. Error: The type t/3742 introduced by this open appears in the signature
  6. File "exten.etex", line 3, characters 6-7:
  7. The value x has no valid type if t/3742 is hidden

is not because x cannot be given any type other than t, which only existslocally. Although the above would be OK if x too was local:

  1. module M: sig end = struct
  2. open struct
  3. type t = A
  4. end
  5. open struct let x = A end
  6. end
  7. module M : sig end

Inside signatures, extended opens are limited to extended module paths,

  1. module type S = sig
  2. module F: sig end -> sig type t end
  3. module X: sig end
  4. open F(X)
  5. val f: t
  6. end
  7. module type S =
  8. sig
  9. module F : sig end -> sig type t end
  10. module X : sig end
  11. val f : F(X).t
  12. end

and not

  1. open struct type t = int end

In those situations, local substitutions(see 8.8.2)can be used instead.

Beware that this extension is not available inside class definitions:

  1. class c =
  2. let open Set.Make(Int) in
  3. ...