I have a module signatures like this:
module type Base_X = sig
type t
end
module type Base_Y = sig
type t
end
module type A_sig = sig
module Some_X : Base_X
module Some_Y : Base_Y
module Z : sig
val f : Some_X.t -> Some_Y.t
end
end
and two types x and y.
Modules that implement A_sig will define Some_X and Some_Y as extending Base_X and Base_Y in a way that allows instances of x and y to be converted to Some_X.t and from Some_Y.t. For instance, one implementation of Some_X might have type
module type X1_sig = sig
type t
val x_to_string : x -> string
val string_to_t : string -> t
end
For each possible module type like X1_sig there will be a functor X1_func (or function using first-class modules) that takes Some_X1 : X1_sig to (a module containing) a function x -> Some_X1.t, and likewise there will be functors to create functions Some_Y.t -> y.
I would like to define a functor Make that takes a module A : A_sig and appropriate functors X_func and Y_func, and produces a function f : x -> y by chaining X_func, A.Z.f and Y_func. It seems like this isn’t possible to do completely generally, and multiple Make functors are needed for different values of X_func and Y_func. But is there a way to do it more generally than by defining specific versions of Make for each possible pair of X_sig/X_func and Y_sig/Y_func? I would be happy with an approach that handles each X_sig and Y_sig separately, but I can’t work out how to do that (defining a functor/function with type x -> Some_X1.t causes the type constructor Some_X1.t to escape its scope).