为什么functor结果绑定到新模块名称对于调用嵌套函数是必要的?

Val*_*nko 5 ocaml functor

我有:

module Functor(M : sig end) = struct
  module NestedFunctor(M : sig end) = struct
  end 
end
Run Code Online (Sandbox Code Playgroud)

此代码有效:

module V = Functor(struct end)
module W = V.NestedFunctor(struct end)
Run Code Online (Sandbox Code Playgroud)

但这是无效的:

module M = Functor(struct end).NestedFunctor(struct end)
                          (*  ^ Error: Syntax error *)
Run Code Online (Sandbox Code Playgroud)

据我所知,仿函数是一组输入模块和一组允许的输出模块之间的关系.但是这个例子让我理解困惑.为什么functor结果绑定到新模块名称对于调用嵌套函数是必要的?

我的编译器版本= 4.01.0


我是OCaml的新手.当我找到仿函数时,我想象一下

Engine.MakeRunnerFor(ObservationStation
                       .Observe(Matrix)
                       .With(Printer))
Run Code Online (Sandbox Code Playgroud)

我认为它是人类友好的架构符号的好工具.然后我很失望.我明白了:这是语法错误.我认为这种限制会扩大语法,并使其不那么直观.

而我的"为什么?" 主要问题是在语言概念的背景下.

And*_*erg 8

虽然我不认为这种限制是绝对必要的,但可能是由于OCaml的模块类型系统存在某些限制.在没有涉及太多技术细节的情况下,OCaml要求所有中间模块类型都可以表达为语法签名.但是对于仿函数,这有时是不可能的.例如,考虑:

module Functor(X : sig end) = struct
  type t = T of int
  module Nested(Y : sig end) = struct let x = T 5 end 
end
Run Code Online (Sandbox Code Playgroud)

鉴于此定义,仿函数的类型Functor(struct end).Nested无法用OCaml语法表示.它需要是类似的东西

functor(Y : sig end) -> sig val x : Functor(struct end).t end  (* not legal OCaml! *)
Run Code Online (Sandbox Code Playgroud)

但是Functor(struct end).t在OCaml中不是有效的类型表达式,原因相当技术性(简而言之,允许类似的类型会决定哪些类型是相同的 - 在类型检查期间必要时 - 更多涉及).

命名中间模块通常可以避免这种困境.特定

module A = Functor(struct end)
Run Code Online (Sandbox Code Playgroud)

仿函数A.Nested有类型

functor(Y : sig end) -> sig val x : A.t end
Run Code Online (Sandbox Code Playgroud)

通过引用命名的中间结果A.