相互递归模块和函子OCaml中(Mutually recursive module and func

2019-10-22 01:05发布

我已经定义了一个接口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_func来讲B_k.basic_func

还是有我的问题一个更好的模式? 我知道我可以声明complex_impl作为常规函数以basic_func作为一个参数,而无需使用仿函数都:

let complex_impl basic_func params =
    ...
    basic_func ...
    ...

但对我来说complex_impl使用的许多基本功能的A ,我认为函子的范例更清晰,不易出错。

编辑:我跟着这个答案 ,但实际上, A使用某种类型的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 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

Answer 1:

您可以使用递归的模块,就像你会写递归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

注意事项(一) 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


文章来源: Mutually recursive module and functor in OCaml
标签: ocaml