There’s, say, this library that exposes a module M
which has a sub-module N
.
I’m working on a project that has this special type 'a X.t
and a way to create those special values.
I want to use M
and M.N
in the rest of the project and expose those special values for all the types of M
and N
. For convenience, it’d be good to have them in the same namespace. So I can use M.foo : M.t
as provided by the library and M.bar : M.t X.t
as provided by my project. The difficult part becomes M.N.bar : M.N.t X.t
.
More concrete example below, with code.
What’s the recommendations for that?
Can I do it without repeating the name of all the exported values in M
/M.N
?
And more fundamentally: why isn’t module shadowing a thing?
Setup:
(* Toy library *)
module M = struct
type t = Int of int | Float of float
let int i = Int i
let float f = Float f
module N = struct
type t = (int * float)
let cons i f = (i, f)
let int (i, _) = i
let float (_, f) = f
end
end
(* Toy module *)
module X = struct
type 'a t = ('a * string)
let name ~name x = (x, name)
end
V1: Partial extension
(* Adding X capability to M *)
module M = struct
include M
type named = t X.t
let name (v: t) : named = X.name ~name:"M" v
end
V2: Complete but incorrect extension (Multiple definition of the module name N. Names must be unique in a given structure or signature.
)
(* Adding X capability to M *)
module M = struct
include M
type named = t X.t
let name (v: t) : named = X.name ~name:"M" v
module N = struct
include N
type named = t X.t
let name (v: t) : named = X.name ~name:"M.N" v
end
end
V3: Complete but verbose
(* Adding X capability to M *)
module M = struct
type t = M.t = Int of int | Float of float
let int = M.int
let float = M.float
type named = t X.t
let name (v: t) : named = X.name ~name:"M" v
module N = struct
type t (* = M.N.t *) = (int * float)
let cons = M.N.cons
let int = M.N.int
let float = M.N.float
type named = t X.t
let name (v: t) : named = X.name ~name:"M.N" v
end
end
V4: Alternative (using a separate module/namespace)
module M_X = struct
type named = M.t X.t
let name (v: M.t) : named = X.name ~name:"M" v
module N_X = struct
type named = M.N.t X.t
let name (v: M.t) : named = X.name ~name:"M.N" v
end
end
Ideally, I’d like something like V2: concise within a single namespace. But only V3 (verbose) and V4 (separate namespace) work. Ideas? Suggestions?