Вам просто нужны дополнительные аннотации, чтобы убедить типографа:
let create (type t0) (m : (module Component.S with type t = t0)) data =
let module M = (val m) in M.create data
Что можно сократить на:
let create (type t0) (module M : Component.S with type t = t0) data =
M.create data
В аннотации (type t)
вводится локальный абстрактный тип данных. Вне функции этот тип превращается в переменную универсального типа, поэтому ему присваивается тип:
val create : (module Component.S with type t = 'a) -> 'a -> Component.t_data
Вы можете использовать локально абстрактный тип, как и любой другой тип, в частности, вы можете поместить его также в локально определенные модули:
let inject (type t0) data =
let module M0 = struct type t = t0 end in
let module M = Component.Make(M0) in
M.create data
val make : 'a -> Component.t_data