OCaml 中的相互递归模块和仿函数
Mutually recursive module and functor in OCaml
我已经定义了一个接口 A
供多个仿函数使用,特别是 MyFunctor
:
module type A = sig
val basic_func: ...
val complex_func: ...
end
module MyFunctor :
functor (SomeA : A) ->
struct
...
let complex_impl params =
...
(* Here I call 'basic_func' from SomeA *)
SomeA.basic_func ...
...
end
现在我想定义一个模块 B
来实现接口 A
。特别是, complex_func
的实现应该使用 basic_func
through complex_impl
in MyFunctor
:
module B = struct
let basic_func = ...
let complex_func ... =
let module Impl = MyFunctor(B) in
Impl.complex_impl ...
end
但是,此代码无法编译,因为 B
未在 MyFunctor(B)
的上下文中完全声明。很明显B
依赖MyFunctor(B)
,而MyFunctor(B)
本身又依赖B
,所以我尝试在模块B
上使用rec
关键字,但是没有用出。
那么,是否可以做这样的事情?这将很有用,因为我有几个模块 B_1, ..., B_n
在 B_k.basic_func
.
方面使用 B_k.complex_func
的相同实现
或者我的问题有更好的模式吗?我知道我可以将 complex_impl
声明为以 basic_func
作为参数的常规函数,而根本不使用仿函数:
let complex_impl basic_func params =
...
basic_func ...
...
但在我的例子中complex_impl
使用了A
的许多基本功能,我认为函子的范式更清晰,更不容易出错。
编辑: 我遵循了 ,但实际上,A
使用了一些专门用于 [=18= 的类型 t
] :
module type A = sig
type t
val basic_func: t -> unit
val complex_func: t -> unit
end
module MyFunctor :
functor (SomeA : A) ->
struct
let complex_impl (x : SomeA.t) =
SomeA.basic_func x
...
end
module rec B : A = struct
type t = int
val basic_func (x : t) = ...
val complex_func (x : t) =
let module Impl = MyFunctor(B) in
Impl.complex_impl x
end
现在我收到错误(x
行 Impl.complex_impl x
):
This expression has type t = int but an expression was expected of type B.t
编辑 2: 我用以下代码解决了第二个问题:
module rec B :
A with type t = int
= struct
type t = int
...
end
您可以像编写递归 let
绑定一样使用递归模块
module type A = sig
val basic_func : unit -> int
val complex_func : unit -> int
end
module MyFunctor =
functor (SomeA : A) ->
struct
let complex_impl = SomeA.basic_func
end
module rec B : A = struct
let basic_func () = 0
let complex_func () =
let module Impl = MyFunctor(B) in
Impl.complex_impl ()
end
注意 (a) B
定义中的 module rec
位和 (b) 我需要为递归模块定义提供模块签名。
# B.basic_func ();;
- : int = 0
# B.complex_func ();;
- : int = 0
但是,有一点需要注意,因为签名 A
只有值是函数类型,所以这才有效。因此它被称为 "safe module"。如果 basic_func
和 complex_func
是值而不是函数类型,那么它会在编译时失败
Error: Cannot safely evaluate the definition
of the recursively-defined module B
我已经定义了一个接口 A
供多个仿函数使用,特别是 MyFunctor
:
module type A = sig
val basic_func: ...
val complex_func: ...
end
module MyFunctor :
functor (SomeA : A) ->
struct
...
let complex_impl params =
...
(* Here I call 'basic_func' from SomeA *)
SomeA.basic_func ...
...
end
现在我想定义一个模块 B
来实现接口 A
。特别是, complex_func
的实现应该使用 basic_func
through complex_impl
in MyFunctor
:
module B = struct
let basic_func = ...
let complex_func ... =
let module Impl = MyFunctor(B) in
Impl.complex_impl ...
end
但是,此代码无法编译,因为 B
未在 MyFunctor(B)
的上下文中完全声明。很明显B
依赖MyFunctor(B)
,而MyFunctor(B)
本身又依赖B
,所以我尝试在模块B
上使用rec
关键字,但是没有用出。
那么,是否可以做这样的事情?这将很有用,因为我有几个模块 B_1, ..., B_n
在 B_k.basic_func
.
B_k.complex_func
的相同实现
或者我的问题有更好的模式吗?我知道我可以将 complex_impl
声明为以 basic_func
作为参数的常规函数,而根本不使用仿函数:
let complex_impl basic_func params =
...
basic_func ...
...
但在我的例子中complex_impl
使用了A
的许多基本功能,我认为函子的范式更清晰,更不容易出错。
编辑: 我遵循了 A
使用了一些专门用于 [=18= 的类型 t
] :
module type A = sig
type t
val basic_func: t -> unit
val complex_func: t -> unit
end
module MyFunctor :
functor (SomeA : A) ->
struct
let complex_impl (x : SomeA.t) =
SomeA.basic_func x
...
end
module rec B : A = struct
type t = int
val basic_func (x : t) = ...
val complex_func (x : t) =
let module Impl = MyFunctor(B) in
Impl.complex_impl x
end
现在我收到错误(x
行 Impl.complex_impl x
):
This expression has type t = int but an expression was expected of type B.t
编辑 2: 我用以下代码解决了第二个问题:
module rec B :
A with type t = int
= struct
type t = int
...
end
您可以像编写递归 let
绑定一样使用递归模块
module type A = sig
val basic_func : unit -> int
val complex_func : unit -> int
end
module MyFunctor =
functor (SomeA : A) ->
struct
let complex_impl = SomeA.basic_func
end
module rec B : A = struct
let basic_func () = 0
let complex_func () =
let module Impl = MyFunctor(B) in
Impl.complex_impl ()
end
注意 (a) B
定义中的 module rec
位和 (b) 我需要为递归模块定义提供模块签名。
# B.basic_func ();;
- : int = 0
# B.complex_func ();;
- : int = 0
但是,有一点需要注意,因为签名 A
只有值是函数类型,所以这才有效。因此它被称为 "safe module"。如果 basic_func
和 complex_func
是值而不是函数类型,那么它会在编译时失败
Error: Cannot safely evaluate the definition
of the recursively-defined module B