Unlike let
declarations, type
declarations in OCaml are automatically
recursive. This seems harmless at first, but it actually causes more trouble
than it’s worth. To see why, let’s look at an example. Here’s a simple signature
that uses nested modules and that adopts the reasonable convention of using t
for the primary type of a module.
module Thing : sig
type t
module Collection : sig
type t
end
val create : string -> t
val collect : t list -> Collection.t
end
Unfortunately, implementing this is made more painful by the fact that type declarations are recursive by default. If you do the obvious thing:
module Thing = struct
type t = string
module Collection = struct
type t = t list
end
let create x = x
let collect xs = xs
end
You get the following error:
File "type_is_implicitly_rec.ml", line 5, characters 9-20:
The type abbreviation t is cyclic
You can fix this by introducing an extra dummy type definition in between to break the recursion:
module Thing = struct
type t = string
module Collection = struct
type z = t
type t = z list
end
let create x = x
let collect xs = xs
end
This works, but it’s ugly and kind of confusing.