recursion - 跨编译单元的 OCaml 递归模块

标签 recursion module ocaml functor

我正在尝试将以下递归模块拆分为单独的编译单元。具体来说,我希望 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在这个主题上,我希望可以使用 OCaml 的模块语法进行编码:“该提案不支持编译单元之间的递归。然而,后者可以使用单独编译的仿函数进行编码,其固定点稍后使用模块 rec构造”。

我玩过模块 rec 但似乎无法找到一种方法来进行类型检查。在 B 的函数 g 中使用 A 的函数 f 似乎引起了麻烦。

(对于上下文,在原始代码中,At 是指令类型,Bt 是基本块类型。分支指令引用块,块包含指令列表。我想重用不同的基本块类型和关联函数指令集。)

最佳答案

我认为这篇论文是指这样的事情:

(* 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 ) 打印
hello
world

显然,A 的定义和 B我用的是废话,但你应该能够将你自己的定义替换到这个模式中,以及使用命名签名而不是像我那样从字面上写出来。

关于recursion - 跨编译单元的 OCaml 递归模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33479679/

相关文章:

module - Yii2 禁用供应商模块的 Assets

asynchronous - 在 Ocaml Async 中的延迟计算中使用 return

polymorphism - 为什么是弱多态类型?

java - 递归查找字符串中最长的单词

python - 在python中使用递归反转列表

c++ - 特殊情况不返回的递归返回函数

c++ - 在 C++ 中使用 Fortran 模块与 std::thread

java - 关于递归的一些问题

android - 如何在库中使用 Realm

ocaml - 使用 utop 中使用 opam 安装的软件包