是否可以在 OCaml 中打开或使用没有中间模块的仿函数?

Is it possible to open or use a functor without an intermediate module in OCaml?

是否可以在没有中间模块的情况下打开或使用仿函数?例如,假设我们有以下一组模块和仿函数:

module type FOO = sig
    val foo : int -> int
end
module Foo1 : FOO = struct
    let foo x = x+1
end
module Foo2 : FOO = struct
    let foo x = x+2
end

module Bar(Foo : FOO) = struct
    open Foo
    let apply x = foo x
end

如果我们尝试

let _ = Bar(Foo1).apply 1

我们收到错误

Error: Parse error: currified constructor

当然,我们可以用

完成这个
let _ =
    let module Bar' = Bar(Foo1) in
    Bar'.apply 1

但是有点冗长。或者,如果我们定义一个使用仿函数

的模块
module Buz(Foo : FOO) = struct
    open Bar(Foo) 
    let buz x = apply x
end

我们收到错误

Error: This module is not a structure; it has type
       functor (Foo : FOO) -> sig val apply : int -> int end

同样,我们可以用

解决这个问题
module Buz(Foo : FOO) = struct
    module M = Bar(Foo)
    open M
    let buz x = apply x
end

但更冗长。此外,我们在 Buz 中定义了一个新模块 M,这会污染命名空间

module Buz :
  functor (Foo : FOO) ->
    sig module M : sig val apply : int -> int end val buz : int -> int end

真的,我只想 Buz 包含 buz

基本上,我问的是是否缺少某种语法或技巧让我们编写 Bar(Foo1).applyopen Bar(Foo1).

之类的东西

如果您正在访问类型、模块类型或 class 类型,则可以跳过仿函数的实例化。换句话说,它只能在类型表达式内部。示例:

module type T = sig type t end
module Pair (T : T) = struct type t = T.t * T.t end
module Int = struct type t = int end
type int_pair = Pair(Int).t

关于你问题的第二部分,如果你真的想要"want Buz to include buz.",那么你应该使用include:

 module Buz(Foo : FOO) = struct
    include Bar(Foo) 
    let buz x = apply x
 end

openinclude 语句有区别。 open X 不会添加来自 X 的任何定义,而只是将其添加到搜索路径中。 include X 只会将 X 中的所有定义复制粘贴到包含它的位置。

如果你只想在你的模块中使用 buz 而仅此而已,那么你可以使用模块签名隐藏它:

module type Buz = sig val buz : int -> int end

module Buz(Foo : FOO) : Buz = struct
  include Bar(Foo)
  let buz = apply
end