I have:
module Functor(M : sig end) = struct
module NestedFunctor(M : sig end) = struct
end
end
This code is valid:
module V = Functor(struct end)
module W = V.NestedFunctor(struct end)
But this is invalid:
module M = Functor(struct end).NestedFunctor(struct end)
(* ^ Error: Syntax error *)
As I understand, a functor is a relation between a set of input modules and a set of possible output modules. But this example confuses my understanding. Why is the binding of the functor result with a new module name required to call nested functor of initial functor?
My compiler version = 4.01.0
I'm new to OCaml. When I found functors I imagined something as
Engine.MakeRunnerFor(ObservationStation
.Observe(Matrix)
.With(Printer))
I thought it is a good tool for the human-friendly architecture notation. Then I was disappointed. Of course, this is a syntax error and I understand that. But I think this restriction inflates grammar and makes it less intuitive. And my "Why?" in the main question is in the context of the concept of language.
While I don't believe that this restriction is strictly necessary, it is probably motivated by certain limitations in OCaml's module type system. Without going into too much technical detail, OCaml requires all intermediate module types to be expressible as syntactic signatures. But with functors, that sometimes isn't possible. For example, consider:
module Functor(X : sig end) = struct
type t = T of int
module Nested(Y : sig end) = struct let x = T 5 end
end
Given this definition, the type of the functor Functor(struct end).Nested
can't be expressed in OCaml syntax. It would need to be something like
functor(Y : sig end) -> sig val x : Functor(struct end).t end (* not legal OCaml! *)
but Functor(struct end).t
isn't a valid type expression in OCaml, for reasons that are rather technical (in short, allowing a type like that would make deciding what types are equal -- as necessary during type checking -- much more involved).
Naming intermediate modules often avoids this dilemma. Given
module A = Functor(struct end)
the functor A.Nested
has type
functor(Y : sig end) -> sig val x : A.t end
by referring to the named intermediate result A
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With