跨编译单元的OCaml递归模块 [英] OCaml recursive modules across compilation units

查看:79
本文介绍了跨编译单元的OCaml递归模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将以下递归模块拆分为单独的编译单元.具体来说,我希望B位于自己的b.ml中,以便能够与其他A一起重用.

I'm trying to split the following recursive modules into separate compilation units. Specifically, I'd like B to be in its own b.ml, to be able to reuse it with other A's.

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 });;

我不知道如何将其拆分为多个单元.

I can't figure out how to split it across units.

以下主题的Xavier Leroy的 paper 给我希望可以使用OCaml的模块语法进行编码:该建议不支持编译单元之间的递归.但是,可以使用单独编译的函子对后者进行编码,稍后将使用模块rec构造获取其固定点".

The following sentence from Xavier Leroy's paper on the topic gives me hope that it's possible to encode using OCaml's module syntax: "the proposal does not support recursion between compilation units. The latter can however be encoded using separately-compiled functors, whose fix-point is taken later using the module rec construct".

我玩过rec模块,但似乎找不到找到类型的方法.在B的函数g中使用A的函数f似乎会造成麻烦.

I've played around with module rec but can't seem to find a way to make it type-check. The use of A's function f inside B's function g seems to cause the trouble.

(对于上下文,在原始代码中,At是指令类型,而Bt是基本块类型.分支指令引用了块,并且这些块包含指令列表.我想重用基本块类型和相关联的代码具有不同指令集的功能.)

(For the context, in the original code A.t is an instruction type, and B.t is a basic block type. Branch instructions reference blocks, and blocks contain lists of instructions. I'd like to reuse the basic block type and associated functions with different instruction sets.)

推荐答案

我认为本文所指的是这样的东西:

I think the paper is referring to something like this:

(* 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

很显然,我使用的AB的定义是胡说八道,但是您应该能够将自己的定义替换为该模式,以及使用命名签名而不是像我一样将它们写出来.

Obviously, the definitions of A and B I used are nonsense, but you should be able to substitute your own definitions into this pattern, as well as use named signatures instead of writing them out literally like I did.

这篇关于跨编译单元的OCaml递归模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆