Is there a way to get a module to return its own type using a functor submodule?
Example
module type A = {};
module type B = { let varB: int; };
module AMod : A = {};
module BMod : B = { let varB = 42; };
module Fn = (A: A, B: B) => A; /* Lets say this does some complex function that returns Type A */
module A2 = Fn(AMod, BMod);
What I want is a Fluent interface where a functor would be in A which returns its own type so it would look like
module type C = { module Fn: (B) => C };
module CMod : C = { Fn: (B) => C};
module C2 = CMod.Fn(BMod).Fn(BMod).Fn(BMod).Fn(BMod).Fn(BMod);
Is this possible in Reason or Ocaml?
Thanks
No, this is not possible. Your module type C
would be recursive, which is not allowed. Such a form of recursion could very easily lead to undecidable type checking, given the expressive power of module types.
It seems like you are trying to shoehorn an object-oriented pattern onto modules, which won't usually work -- ML modules are very much a functional language in nature. What's wrong with the following?
module A2 = Fn(Fn(Fn(Fn(Fn(A, B), B), B), B), B)
If you are interested in shortening the general pattern, you can actually implement a module combinator (in plain Ocaml, since I don't know Reason syntax well enough):
module type FN = functor (X:A)(Y:B) -> A
let rec fn n =
if n = 0 then (module (functor (X:A)(Y:B) -> X) : FN)
else (module (functor (X:A)(Y:B) -> (val fn (n-1))(X)(Y)))
module A2 = (val fn 5)(AMod)(BMod)
You could also write combinators that take a list of different B
modules, though I wonder how useful that is going to be in practice.