我有:
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)
我认为它是人类友好的架构符号的好工具.然后我很失望.我明白了:这是语法错误.我认为这种限制会扩大语法,并使其不那么直观.
而我的"为什么?" 主要问题是在语言概念的背景下.
虽然我不认为这种限制是绝对必要的,但可能是由于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.