OCaml中的相互递归模块和仿函数

时间:2015-02-23 21:38:23

标签: 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中的complex_implMyFunctor

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)B本身取决于rec,因此我尝试在模块B上使用B_1, ..., B_n关键字,但它不起作用进行。

那么,有可能做这样的事吗?这将是有用的,因为我有几个模块B_k.complex_funcB_k.basic_func方面使用相同的complex_impl实现。

或者我的问题有更好的模式吗?我知道我可以将basic_func声明为以let complex_impl basic_func params = ... basic_func ... ... 为参数的常规函数​​,而不使用仿函数:

complex_impl

但在我的情况下A使用A的许多基本功能,我认为仿函数的范例更清晰,更不容易出错。

修改:我跟踪了this answer,但实际上,t使用了B专用的某种类型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 xThis expression has type t = int but an expression was expected of type B.t ):

module rec B :
    A with type t = int
= struct
    type t = int
    ...
end

编辑2:我使用以下代码解决了第二个问题:

{{1}}

1 个答案:

答案 0 :(得分:4)

您可以像编写递归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)module rec定义中的B位和(b)我需要为递归模块定义提供模块签名。

# B.basic_func ();;
- : int = 0
# B.complex_func ();;
- : int = 0

然而,有一点需要注意,因为签名A只有值是函数类型,所以这只能起作用。因此它被称为“安全模块”。如果basic_funccomplex_func是值而不是函数类型,那么它将在编译时失败

Error: Cannot safely evaluate the definition
       of the recursively-defined module B
相关问题