2015-02-23 56 views
1

我已经和特别是通过MyFunctor定义的接口A由几个仿函数可以使用:相互递归模块和函子OCaml中

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实施应在MyFunctor使用basic_func通过complex_impl

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,所以我试图在模块B上使用rec关键字,但它没有解决。

那么,是否有可能做这样的事情?这将是有用的,因为我有几个模块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许多基本功能,我认为范式函子更清晰,更不容易出错。

编辑:我跟着this answer,但事实上,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 

回答

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 

注意事项(一)在B和(b),我的定义module rec位我们需要为递归模块定义提供模块签名。

# 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 
+0

谢谢您的回答,我写了'模块REC B = struct',错过了'B:A'一部分。 – Steakfly 2015-02-24 13:13:44

+0

但是,我仍然有错误(请参阅我的编辑)... – Steakfly 2015-02-24 13:50:48