Stephen taught me a neat trick a while back. Suppose you want to define a some mutually recursive types

  1. type even = Zero | Even_succ of odd
  2. and odd = Odd_succ of even

Now suppose you want to do this in such a way that each type belongs to its own module. Since OCaml requires signature annotations in recursive module definitions, I thought this required one to write out the type definitions twice.

  1. module rec Even : sig
  2. type t = Zero | Succ of Odd.t
  3. end = struct
  4. type t = Zero | Succ of Odd.t
  5. end
  6. and Odd : sig
  7. type t = Succ of Even.t
  8. end = struct
  9. type t = Succ of Even.t
  10. end

However, Stephen showed me the following trick

  1. module rec Even : sig
  2. type t = Zero | Succ of Odd.t
  3. end = Even
  4. and Odd : sig
  5. type t = Succ of Even.t
  6. end = Odd

Whoa! We're seemingly defining some modules out of thin air! This looks very analogous to the ill-founded definitions

  1. let rec even : some_type_for_even = even
  2. and odd : some_type_for_odd = odd

But since we're only defining types here, this trick cannot cause undefined values to sneak into our program. We have effectively gotten OCaml to infer the definition of a module from its signature in the special case where the module only contains type definitions (it may also contain module type definitions).

Mutual recursion is not required for this to work. You can also wrap everything up into a single recursively defined parent module if you like.

  1. module rec Layered : sig
  2. module Even : sig
  3. type t =
  4. | Zero
  5. | Succ of Layered.Odd.t
  6. end
  7. module Odd : sig
  8. type t =
  9. | Succ of Layered.Even.t
  10. end
  11. end = Layered

Sadly, this trick is somewhat limited in that it doesn't work with our Type_conv pre-processors since there are only type specifications here and not type definitions upon which to hang a "with sexp" (for example).