我试图将以下递归模块拆分为单独的编译单元。具体来说,我希望 B 位于它自己的 b.ml 中,以便能够与其他 A 一起重用它。
module type AT = sig
type b
type t = Foo of b | Bar
val f : t -> b list
end
module type BT = sig
type a
type t = { aaa: a list; bo: t option }
val g : t -> t list
end
module rec A : (AT with type b = B.t) = struct
type b = B.t
type t = Foo of b | Bar
let f = function Foo b -> [ b ] | Bar -> []
end
and B : (BT with type a = A.t) = struct
type a = A.t
type t = { aaa: a list; bo: t option }
let g b =
let ss = List.flatten (List.map A.f b.aaa) in
match b.bo with
| Some b' -> b' :: ss
| None -> ss
end
let a = A.Bar;;
let b = B.({ aaa = [a]; bo = None });;
let c = A.Foo b;;
let d = B.({ aaa = [a;c]; bo = Some b });;
我不知道如何将其划分为不同的单元。
以下句子来自 Xavier Leroy 的paper http://caml.inria.fr/pub/papers/xleroy-recursive_modules-03.pdf关于这个主题给了我希望,可以使用 OCaml 的模块语法进行编码:“该提案不支持编译单元之间的递归。但是,后者可以使用单独编译的函子进行编码,稍后使用模块 rec 获取其固定点构造”。
我已经尝试过 module rec 但似乎找不到一种方法来对其进行类型检查。在 B 的函数 g 中使用 A 的函数 f 似乎会引起麻烦。
(就上下文而言,在原始代码中,A.t是指令类型,B.t是基本块类型。分支指令引用块,块包含指令列表。我想重用基本块类型和相关函数指令集。)
我认为这篇论文指的是这样的事情:
(* a.ml *)
module F (X : sig val x : 'a -> 'a end) =
struct
let y s = X.x s
end
(* b.ml *)
module F (Y : sig val y : 'a -> 'a end) =
struct
(* Can use Y.y s instead to get infinite loop. *)
let x s = Y.y |> ignore; s
end
(* c.ml *)
module rec A' : sig val y : 'a -> 'a end = A.F (B')
and B' : sig val x : 'a -> 'a end = B.F (A')
let () =
A'.y "hello" |> print_endline;
B'.x "world" |> print_endline
运行这个(ocamlc a.ml b.ml c.ml && ./a.out
) prints
hello
world
显然,定义A
and B
我使用的是无意义的,但你应该能够将你自己的定义替换到这个模式中,以及使用命名签名而不是像我一样逐字写出它们。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)