I have read many posts here about modules but the following still isn’t clear to me. If Foo is a module of type FOO, and BAR is a module type for a functor that accepts some Foo:FOO and defines something else, how can I get the “something else”? In other words how do I say that some module Bar has type BAR Foo? In code:
module type FOO =
sig
type t
val x : t
end
module type BAR =
functor (Foo:FOO) ->
sig
val y : Foo.t
end
module Foo : FOO =
struct
type t = bool
let x = true
end
(** Doesn't work *)
module Bar : BAR Foo =
struct
let y = Foo.x
end
(** Doesn't work *)
module type BAR_At_Foo = BAR (Foo)
How can I, or why can’t I, do this?
My understanding of the module system is such that I think this is completely reasonable and doesn’t pose any problems whatsoever–it is approximately like instantiating a dependent product type at a particular value, all of which is known at compile time. So please disabuse me of this idea if I’m being naïve.
In anticipation of questions: My use case is that Foo is some configuration module that defines some types and Bar:BAR is a module that provides functionality whose types depend on the types from Foo. My library accepts a Foo:FOO and Bar:BAR(Foo) and returns something very complicated. I am aware that I could merge Foo and Bar into one massive module, or better yet a record, but I’m very interested in understanding this from a dependent types perspective.
(I hope the answer is not that I’ve encoded some obvious undecidability that I’m blindly overlooking.)