Recursion OCaml中的递归函子

Recursion OCaml中的递归函子,recursion,module,ocaml,Recursion,Module,Ocaml,这个问题类似于,但我想声明一个递归函子,而不是递归模块。因此,我: 接口A: module type A = sig type t val basic_func: ... val complex_func: ... end 根据A.basic\u func实现A.complex\u func的函子ComplexImpl: module ComplexImpl (SomeA : A) = struct let complex_impl params =

这个问题类似于,但我想声明一个递归函子,而不是递归模块。因此,我:

接口
A

module type A = sig
    type t
    val basic_func: ...
    val complex_func: ...
end
根据
A.basic\u func
实现
A.complex\u func
的函子
ComplexImpl

module ComplexImpl (SomeA : A) =
struct
    let complex_impl params =
        SomeA.basic_func ...
        ...
end
另一个界面
I

module type I = sig
    type t
    ...
end
以及一个函子
B
,它接受类型为
I
的参数,实现接口
a
,并使用
complementpl
实现
复杂函数。我想这样写:

(* 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
module rec RealB = B(SomeI)(RealB)
module RealB = B(SomeI)
但我不能声明递归函子


我发现实现递归函子的唯一方法是自己对其进行参数化:

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
然后像这样使用它:

(* 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
module rec RealB = B(SomeI)(RealB)
module RealB = B(SomeI)

但是语法冗长,不太安全(如果有人输入的参数不同于
RealB
),并且如果
RealB
本身就是一个函子,那么它会变得非常棘手……

我找到了一个解决方案:

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
我可以这样使用它:

(* 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
module rec RealB = B(SomeI)(RealB)
module RealB = B(SomeI)

递归模块具有以下形式的语法限制:

module rec Name : module_type = module_expr
这意味着递归函子不能使用以下命令声明:

module rec Name (Arg : module_type) : module_type = module_expr
但必须写下:

module rec Name : functor (Arg : module_type) -> module_type =
  functor (Arg : module_type) -> module_expr

但是,这在我的例子中不起作用,因为
B(SomeI)
的签名是
A,类型为t=SomeI.t
。因此,就您的术语而言,
Name
module_type
依赖于
Arg
,这是无效的(除非我遗漏了什么)。在您的情况下,它可以正常工作。
名称
模块类型
也将是
函子(Arg:modtype)->modtype
(因为
名称
的类型是函子类型)。我将更新我的答案以使其更清楚。在我的情况下,我得到以下错误:
无法安全地评估递归定义的模块B的定义
您的代码不一定有充分的依据,因为B(SomeI)的定义涉及调用B(SomeI)。在您在问题中给出的解决方案中,您正在利用OCaml提供的一种变通方法——如果模块是一个只包含函数的结构,那么它允许潜在的无依据递归(如果它实际上是无依据的,则在运行时会引发异常)。函子不支持这种变通方法。就我个人而言,如果可能的话,我会避免使用递归模块。有时它们是不可避免的,但通常有一种更简单的方法没有它们。这只适用于函子不是真正递归的情况,但只有它的结果是递归的。一般的解决方案就是利奥所展示的。它允许函子应用自身,即使使用不同的参数。