Multiple inclusion problem

For example I have a very abstract logic in module D, which in fact extends concepts of modules A and B, but both should include the same types and functions from module C. Think of A and B as a different versions of the same logic, and D can switch between these two branches on the fly.

I thought about something like this:

    module C = struct
       type common_struct = {
         field1: int;
       }
    end

    module A = struct
       include C

       let some_func1 _ = () (* Uses type from C *)
    end

    module B = struct
       include C

       let some_func2 _ = () (* Uses type from C *)
    end

    module D  = struct
       include A
       include B
    end

But this code obviously throws an error. Are there any solutions for this?

Your code throws an error because you have multiple definition of the same type.

(* I used `t` as the type name in my code *)
module D = struct
  include A
  include B
end;;
Error: Multiple definition of the type name t.
       Names must be unique in a given structure or signature.

The solution is to use destructive substitution with your include:

module D = struct
  include A
  include (B : module type of B  with type t := t)
end;;
module D :
  sig
    type t = B.t = { field1 : int; }
    val some_func1 : t -> unit
    val some_func2 : t -> unit
  end
5 Likes

Note that the original example will start working with OCaml 4.08.

(See also: https://blog.janestreet.com/plans-for-ocaml-408/#shadowing-of-items-from-include)

4 Likes