在OCaml中是否可以在没有中间模块的情况下打开或使用函子?
是否可以在没有中间模块的情况下打开或使用函子?例如,假设我们有以下一组模块和函子:在OCaml中是否可以在没有中间模块的情况下打开或使用函子?,ocaml,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
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
Error: This module is not a structure; it has type
functor (Foo : FOO) -> sig val apply : int -> int end
当然,我们可以通过
let _ =
let module Bar' = Bar(Foo1) in
Bar'.apply 1
module Buz(Foo : FOO) = struct
module M = Bar(Foo)
open M
let buz x = apply x
end
但是有点冗长。或者,如果我们定义一个使用函子的模块
module Buz(Foo : FOO) = struct
open Bar(Foo)
let buz x = apply x
end
我们得到了错误
Error: Parse error: currified constructor
Error: This module is not a structure; it has type
functor (Foo : FOO) -> sig val apply : int -> int end
同样,我们可以用
let _ =
let module Bar' = Bar(Foo1) in
Bar'.apply 1
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)。应用或openbar(Foo1)
如果访问类型、模块类型或类类型,可以跳过functor的实例化。换句话说,只能在类型表达式内部执行。例如:
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
open
和include
语句之间存在差异openx
不会从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
在第二种情况下,如果可能的话,我根本不想要额外的定义。真的,我只想buz
出现在签名中,这样做不需要手动定义新签名就好了。在OCaml中不能这样做。这是有原因的。主要原因是模块可以有任意的副作用和非平凡的表示。他们需要一个居住的地方。