Ste*_*fly 6 recursion ocaml module
这个问题类似于这一个,但我要声明一个递归函数对象,而不是递归模块。所以我有 :
一个界面A:
module type A = sig
type t
val basic_func: ...
val complex_func: ...
end
Run Code Online (Sandbox Code Playgroud)
在以下方面ComplexImpl实现的函子:A.complex_funcA.basic_func
module ComplexImpl (SomeA : A) =
struct
let complex_impl params =
SomeA.basic_func ...
...
end
Run Code Online (Sandbox Code Playgroud)
另一个界面I:
module type I = sig
type t
...
end
Run Code Online (Sandbox Code Playgroud)
以及一个B接受类型参数的函子I,实现接口A并用于ComplexImpl实现complex_func。我想写这样的东西:
(* I can't write 'rec' here *)
module rec B (SomeI : I) :
A with type t = SomeI.t
= struct
type t = SomeI.t
(* this line does not work *)
module Impl = ComplexImpl(B(I))
let basic_func (x : t) = ...
let complex_func (x : t) =
Impl.complex_impl x
end
Run Code Online (Sandbox Code Playgroud)
但是我不能声明一个递归函子......
我发现实现递归函子的唯一方法是自行对其进行参数化:
module B (SomeI : I) (CopyOfB : A with type t = SomeI.t) :
A with type t = SomeI.t
= struct
type t = SomeI.t
(* this line works *)
module Impl = ComplexImpl(CopyOfB)
let basic_func (x : t) = ...
let complex_func (x : t) =
Impl.complex_impl x
end
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
module rec RealB = B(SomeI)(RealB)
Run Code Online (Sandbox Code Playgroud)
但是语法很冗长,不是很安全(如果有人把一个不同于 的参数怎么办RealB)而且如果RealB它本身是一个函子,它就会变得非常棘手......
递归模块有一个语法限制,其形式为:
module rec Name : module_type = module_expr
Run Code Online (Sandbox Code Playgroud)
这意味着不能使用以下方式声明递归函子:
module rec Name (Arg : module_type) : module_type = module_expr
Run Code Online (Sandbox Code Playgroud)
但必须写成:
module rec Name : functor (Arg : module_type) -> module_type =
functor (Arg : module_type) -> module_expr
Run Code Online (Sandbox Code Playgroud)
我找到了一个解决方案:
module B (SomeI : I) = struct
(* introduce a recursive module Implementation *)
module rec Implementation :
A with type t = SomeI.t
= struct
type t = SomeI.t
(* use Implementation here *)
module Impl = ComplexImpl(Implementation)
let basic_func (x : t) = ...
let complex_func (x : t) =
Impl.complex_impl x
end
(* include the code of Implementation here *)
include Implementation
end
Run Code Online (Sandbox Code Playgroud)
我可以这样使用它:
module RealB = B(SomeI)
Run Code Online (Sandbox Code Playgroud)