问题
I have two modules. One defines a variant type:
module A = struct
type foo = Bar of material | Baz | Boo
(* other stuff *)
end
and I would like to be able to use foo
's variants both as constructors and as left-hand-sides in another module
module B = struct
type foo = A.foo (* I can abbreviate A.foo by assigning it a local alias *)
let f (x : foo) = match x with
| Bar m -> Bar (g m) (* Any way to abbreviate Bar and friends? *)
| Baz | Boo -> x
end
but per "referring to named objects" I have to prefix the variant names with a module-path:
let f (x : foo) = match x with
| A.Bar m -> A.Bar (g m)
| A.Baz | A.Boo -> x
Is there any way to skip avoid using the module path short of open
ing and pulling in all the other stuff from A
?
回答1:
You can open A locally:
let f (x : foo) = A.(match x with
| Bar m -> Bar (g m)
| Baz | Boo -> x)
or
let f (x : foo) =
let open A in
match x with
| Bar m -> Bar (g m)
| Baz | Boo -> x)
You can define Bar
in a submodule so that less things are exposed:
module A = struct
module BasicDataAndOps = struct
type foo = Bar of material | Baz | Boo
end
open BasicDataAndOps
(* other stuff *)
end
module B = struct
open A.BasicDataAndOps
...
For use outside of patterns, you can define a "smart constructor" in B:
let bar m = A.Bar m
ETA: I forgot about the possibility to restate type definition, described in Ashish Argwal's answer: type foo = A.foo = Bar of material | Baz | Boo
. Given that you already have type abbreviation in your example, this is the best answer.
There is some work on type-based label disambiguation which could be helpful, but it may not get accepted into the language.
回答2:
In addition to the answers lukstafi gave, you can also re-state the constructors when defining B.foo
.
module A = struct
type foo = Bar | Baz
end
module B = struct
type foo = A.foo = Bar | Baz
let f (x : foo) = match x with
| Bar -> "bar"
| Baz -> "baz"
end
来源:https://stackoverflow.com/questions/13538985/abbreviating-constructor-names-in-ocaml