A had a question about mutually recursive modules. It is similar to the example found here.
Check out these two modules. If have intentionally added bug in the
to_b function where it uses the
A.of_int rather than
module rec A : sig type t val of_int : int -> t val to_b : t -> B.t end = struct type t = int let of_int x = x (* With the B.t type annotation, this won't compile. If you remove it, it will compile. *) let to_b x : B.t = A.of_int x end and B : sig type t val of_int : int -> t val to_a : t -> A.t end = struct type t = int let of_int x = x let to_a x : A.t = A.of_int x end
t is abstract for both modules, I expected this
let to_b x = A.of_int x to give an error since
A.t and not
B.t. But the compile error only occurs when I define it with type annotation:
let to_b x : B.t = A.of_int x.
I assume that the reason it compiles fine is the fact that modules
B are defined recursively and since they have the same
type t = int in both implementations, it just works out.
In this case, it doesn’t really matter if you were to remove the type annotation and let it compile, but you could imagine a case where the
B.of_int had some special preconditions that it enforced…e.g., ensuring A types are all positive numbers and B types are all negative numbers. Depending on the specific logic, you could get a runtime error down the line somewhere.
Basically, I’m wondering if this is the expected behavior. From the many Discuss posts about recursive modules, they seem to be a bit tricky, and I suppose it may be best to avoid them if possible…