Functor with an unknown type in its first-class module

Hello :wave:

I want to make a functor, which only needs a single function implementation as its argument.
My problem is, that I don’t want to have to provide the input type of the function in the first-class module (as its type is quite complex and always the same).
Sorry, if the terminology I am using is incorrect :grimacing:
I hope you can understand me anyways.

Is there a way the following simplified example can work?
Basically the 'a should be replaced by the type t which is declared inside Make.

module type S = sig
  val to_string : 'a -> string
end

module Make (Impl : S) = struct
  type t = int

  let to_string : t -> string = Impl.to_string
end

module MyModule = Make (struct
  let to_string = string_of_int
end)

Thank you for your help!

- Torben

Perhaps you can just define the type outside the functor argument ?

type large_type = ...

module MyModule1 = Make (struct type t = large_type let to_string = ... end)
module MyModule2 = Make (struct type t = large_type let to_string = ... end)
(* etc *)

Cheers,
Nicolas

Writing the type is probably the simplest solution.

However, it is possible to use first-class modules to lift an inferred type to the module level:

module type S = sig
  type t
  val to_string: t -> string
end

let make (type a) f : (module S with type t =a) =
  (module struct
    type t = a
    let to_string = f
  end)

module R = (val (make Fun.id))

I use this pattern from time to time when I encode some computation in types with GADTs and want to extract the result of the computation at the module level.

9 Likes

For more info on this technique see the similar example in Real World OCaml: First-Class Modules - Real World OCaml (in the subsection More on Locally Abstract Types).

2 Likes