The strange case of disapearing constructor

Hi, I’d like to understand if the following code is OK.

type t1 = 
| A of int 
| B of string

type t2 = A of string

let f1 v = A v  (* val f1 : string -> t2 = <fun> *)
let f2 v = B v  (* val f2 : string -> t1 = <fun> *)

It compiles without without any warnings, But it feels wrong that the first A constructor of type t1 is not accessible any more, but B still is.

The definition of f1 raises a warning:

Warning 41 [ambiguous-name]: A belongs to several types: t2 t1
The first one was selected. Please disambiguate if this is wrong.

which hints to the way to get back A from the first type:

let f1 v = (A v:t1)

(which raises disambiguated-name warning which is mostly safe to ignore nowadays)

Thanks, I did not get such an warning with 4.11 with just ocaml -c test.ml

Anyway, it’s clear now.

This warning is not activated by default. For quick testing, it might be useful to enable all warnings with ocamlc -w +a -c test.ml.

A good way to disambiguate constructors is to put the types in different modules:

module T1 = struct
  type t = A of int | B of string
end

module T2 = struct
  type t = A of string
end

let f1 v = T1.A v (* val f1 : int -> T1.t = <fun> *)
let f2 v = T2.A v (* val f2 : string -> T2.t = <fun> *)

Modules are cheap to create, so this is easy. It also works nicely for disambiguating between record types with the same field names.

1 Like