Functorizing a library

Have people found ways to functorize whole libraries? By library, I mean a collection of modules written as individual source files. I imagine we would write just mli files without an implementation and have the library exposed as a functor that expects the missing implementation as argument.

This seems doable with a custom build script or something like cppo, but merlin would probably get confused by it. Here’s how it goes:

(* Lib.cppo.mli *)
module type A = sig
  #include "A.mli"
end

module type B = sig
  #include "B.mli"
end

module type T = sig

  type a
  type b

  module C : sig
    #include "C.mli"
  end

  module D : sig
    #include "D.mli"
  end

end

module Make (A : A) (B : B) : T with type a = A.t
                                 and type b = B.t

and

(* Lib.cppo.ml *)
module type A = sig
  #include "A.mli"
end

module type B = sig
  #include "B.mli"
end

module type T = sig

  type a
  type b

  module C : sig
    #include "C.mli"
  end

  module D : sig
    #include "D.mli"
  end

end

module Make (A : A) (B : B) = struct

  type a = A.t
  type b = B.t

  module C = struct
    #include "C.ml"
  end

  module D = struct
    #include "D.ml"
  end

end

and A.mli and B.mli each contain just this:

type t

The other ml and mli files are empty in this example.

This can be compiled as follows:

$ cppo Lib.cppo.mli > Lib.mli && cppo Lib.cppo.ml > Lib.ml && ocamlc -a -o Lib.cma Lib.mli Lib.ml

giving us the following compact signature for the library’s root module Lib:

$ cmitomli Lib.cmi
module type A = sig type t end
module type B = sig type t end
module type T = sig type a type b module C : sig  end module D : sig  end end
module Make :
  functor (A : A) (B : B) ->
    sig type a = A.t type b = B.t module C : sig  end module D : sig  end end

I’m not quite sure about the practicality of all this. It would be very nice to have one file per module or per module interface rather than cramming everything into one giant file, but perhaps that’s the best approach for now. Has anyone tried other approaches?

1 Like