module type Arity =
sig
val arity : nat (* in my real code it has another type *)
end
module S =
functor (A : Arity) -> struct
let check = ...
end
我想在函数check
中使用函数S
而不使用签名Arity
。我读了一流的模块,但仍然不明白如何编写它(在实践中)。这是我的草案代码:
let A = has type of (module Arity)
然后
let M = S (A)
然后我可以通过
调用check
函数
M.check
我试过了:
let f arity = (module (val arity : Arity) : Arity)
它返回:val f : (module Arity) -> (module Arity)
你能帮我写一下这个一流的模块吗?我可以在Ocaml
写一下吗?
同样在(http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual021.html#toc81)第7.14节中说:
“模块表达式(val expr : package-type)
不能在仿函数的主体中使用,......”
我不明白。你能举一个例子来帮我理解吗?
感谢您的帮助。
答案 0 :(得分:5)
我不清楚你在这里想知道什么。显然你会对正常的OCaml模块和仿函数以及OCaml的更新“一流模块”中的一些词语感到困惑。无论如何,我给你一个简短的工作示例与OCaml 4.00.1(不要尝试使用3.12.1,因为事情在4中有所改进),可能它会帮助你:
module type Arity = sig
val arity :int
end
module S = functor (A : Arity) -> struct
let check = A.arity = 2 (* or whatever *)
end
以上是您通过一些简单的修复程序给我们编译的内容。通常使用check,你给出一个签名Arity的实现并将它交给函子S:
module AR = struct
let arity = 3
end
module SAR = S(AR)
let () = Printf.printf "%b\n" SAR.check
让我们使用第一类模块:
let a = (module AR : Arity)
这会将模块AR转换为值并将其绑定到变量a。请注意,parens对于语法是必需的。你还需要给予siganture Arity。您也可以写如下:
let a' : (module Arity) = (module AR)
所以a和a的类型是(模块Arity),你需要以某种方式将它提供给编译器。不幸的是,类型推断对我们没有帮助。
您可以按如下方式将值恢复为模块:
module A' = (val a)
现在您还可以创建函子S的第一个类模块值:
module type RESULT = sig
val check : bool
end
let s (a : (module Arity)) =
let module A = (val a) in
let module SA = S(A) in
(module SA : RESULT)
做的是:取一个值,使其返回模块,将仿函数S应用于它,然后从仿函数应用程序的结果中创建另一个值。单个RESULT是转换所必需的。你不能写(模块SA:sig val check bool end)。我不擅长这里的事情,但我听说,第一类模块值的输入不是结构性的,而是名义上的。您需要在(模块M:X)处为签名命名。
s的类型是(模块Arity) - > (模块结果)。我们将s应用于:
let m = s a
要访问m内部的检查,您需要将其恢复为模块:
let m_check =
let module M = (val m) in
M.check
您可能会失望地看到价值< - >模块转化是明确的,但这就是它的工作原理......