I'd like to define a type alias for constructors to be reused in a given module, without having to prefix them by the path to the module where they're defined. I'd also like to avoid "polluting" the latter module by doing an open
/include
that would import too many definitions.
Here's an example of what I'd like (which does not compile):
module A = struct
type t = Red | Blue
end
module B = struct
type t = A.t
let f = function
| Red -> 1 (*Error: Unbound constructor Red*)
| Blue -> 0
let
end
Doing include A
or open A
inside B would both work here (Red
and Blue
would be valid), but both will add definitions to B, "polluting" it.
open
will do the least amount of damage, but still allows mistakes to be made, e.g. if A
defines a symbol that is accidentally used in B
due to the open
, I won't have a compilation error.
Is there a way to avoid this "pollution" while preventing me from having to type A.Red
/A.Blue
in module B?
Yes there is.
You can, when defining t
in B
, state that it is equal to A.t
and rewrite the list of its constructors:
module B = struct
type t = A.t = Red | Blue
let f = function
| Red -> 1
| Blue -> 0
end
The typechecker will verify that the definition is the exact same as in A
so even if you modify your type definition in A you'll be reminded to change it in B
as well (yes, you type twice the same thing but it's a simple dumb copy/paste).
With OCaml 4.02.x and later you can use ppx_import (https://github.com/whitequark/ppx_import).
a.ml
type t = A | B
b.ml
(* This gives a similar result to PatJ's answer *)
type a_t = [%import: A.t]
let foo = function
| A -> 0
| B -> 1
It's less explicit than PatJ's suggested approach. The ppx may be simpler if you're working with a large type definition or if A.t
is changing frequently during development.
A downside of the ppx approach is that you can't [%import]
types from within the same source file. The imported type needs to be defined in a separate compilation unit.
The answer by @PatJ is a good one. Here is another approach that is sometimes useful: you can define three modules, one containing only your type, and then A
and B
. Open the first module in A
and B
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With