2015-02-23 42 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