After being lazy for some years, I decided to get a grasp of first class modules. So far so good but I’m currently stuck within my experiments mainly in relation to the way one can add typing constraints to such module values.
Writing a function
apply of type
('a -> 'b) -> 'a -> 'b is done trivially as
let apply f arg = f arg.
Suppose that it is not one function but a set of functions I want to give to
apply. I can define a module and use first class modules.
module type MTYPE = sig type input type output val f: input -> output end let apply1 m arg = let module M = (val m: MTYPE) in M.f arg
This code raise an error: The type constructor M.input would escape its scope. One possible solution is to use existential types:
let apply2 (type a b) m arg = let module M = (val m: MTYPE with type input = a and type output = b) in M.f arg
This code compiles and works great but it forces me to define the types
output in the implementations though the typer computed them…
Q1: is there a way to do this without requiring the developer to define
output? I would have liked to say:
let apply3 (type a b) m arg = let module M = (val m: sig val f: a -> b end) in M.f arg
but the compiler raises an error: invalid package type: only module type identifier and ‘with type’ constraints are supported.
apply2, I now want the module argument to be a functor. For example, supposing:
module type PTYPE = sig type ('a,'b) ty end module type MTYPE' = functor (P:PTYPE) -> MTYPE module I: PTYPE = struct type ('a,'b) ty = ('a * 'b) list end
I would like to write:
let apply4 (type a b) m arg = let module M = (val m: functor (P:PTYPE) -> sig val f: a -> b end) (I) in M.f arg
which is still not possible so I tried:
let apply5 (type a b) m arg = let module M = (val m: MTYPE' with type input = a and type output = b) (I) in M.f arg
That does not work: Error: This module type is not a signature.
Q2: is there a way to link the input and output type of the functor to my existential types?
Thank you in advance