(* TEST expect; *) type (_, _) equ = Refl : ('q, 'q) equ module type Ty = sig type t end type 'a modu = (module Ty with type t = 'a) type 'q1 packed = P : 'q0 modu * ('q0, 'q1) equ -> 'q1 packed (* Adds a module M to the environment where M.t equals an existential *) let repack (type q) (x : q packed) : q modu = match x with | P (p, eq) -> let module M = (val p) in let Refl = eq in (module M) [%%expect{| type (_, _) equ = Refl : ('q, 'q) equ module type Ty = sig type t end type 'a modu = (module Ty with type t = 'a) type 'q1 packed = P : 'q0 modu * ('q0, 'q1) equ -> 'q1 packed val repack : 'q packed -> 'q modu = |}] (* Same, using a polymorphic function rather than an existential *) let mkmod (type a) () : a modu = (module struct type t = a end) let f (type foo) (intish : (foo, int) equ) = let module M = (val (mkmod () : foo modu)) in let Refl = intish in let module C : sig type t = int end = M in () [%%expect{| val mkmod : unit -> 'a modu = val f : ('foo, int) equ -> unit = |}]