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

时间:2015-08-19 18:19:45

标签: 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

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

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)之类的内容。

1 个答案:

答案 0 :(得分:3)

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

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

关于你问题的第二部分,那么如果你真的想“想要Buz包含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