在OCaml中使用一流的模块

时间:2013-03-25 02:31:50

标签: module ocaml functor

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)不能在仿函数的主体中使用,......”

我不明白。你能举一个例子来帮我理解吗?

感谢您的帮助。

1 个答案:

答案 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

您可能会失望地看到价值< - >模块转化是明确的,但这就是它的工作原理......