Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abbreviating constructor names in Ocaml

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 opening and pulling in all the other stuff from A?

like image 429
Mike Samuel Avatar asked Nov 24 '12 06:11

Mike Samuel


2 Answers

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.

like image 105
lukstafi Avatar answered Nov 15 '22 10:11

lukstafi


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
like image 44
Ashish Agarwal Avatar answered Nov 15 '22 10:11

Ashish Agarwal