4
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内部的函数。我阅读了一流的模块,但仍然不明白如何编写它(在实践中)。这是我的草稿代码:SArity

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

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

谢谢您的帮助。

4

1 回答 1

6

我不清楚您想在这里了解什么。显然,您对普通 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

以上是你给我们的一些简单的修复来编译。通常要使用检查,您提供签名 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。请注意,括号对于语法是必需的。您还需要提供签名 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 所做的是:取一个值,将其返回到模块,将仿函数 S 应用于它,然后从仿函数应用的结果中生成另一个值。签名 RESULT 是转换所必需的。你不能写(模块 SA : sig val check bool end)。我不擅长这里的事情,但我听说,第一类模块值的输入不是结构性的而是名义上的。您需要在(模块 M : X)处为签名命名。

s 的类型是(模块 Arity)->(模块 RESULT)。让我们将 s 应用于 a:

let m = s a

要访问 m 内部的检查,您需要将其重新设置为模块:

let m_check =
  let module M = (val m) in
  M.check

您可能会失望地看到 value<->module 转换是明确的,但这就是它的工作原理......

于 2013-03-25T04:52:21.757 回答