OCaml交联

Jac*_*ack 6 recursion linker ocaml module cross-reference

参考链接如何在OCaml中工作?

例如,假设我有3个模块声明为

  • A.ml
  • B.ml
  • C.ml

其中

  • A需要BC
  • B 需求 A

我该如何进行编译?

由于订单是相关的,ocamlc或者ocamlopt我如何修复B和之间的交叉参考A

我想首先他们都汇编成.cmoocamlc -c,然后链接所有的人都在一起,但自从与交换参数将刚刚从一个模块移动到另一个问题没有成功.

具体错误是:

错误:链接A.cmo时出错:引用未定义的全局`B'

(或者反之,如果我交换了args的顺序)

我认为这是一个简单的问题,但我无法解决它...提前感谢

nlu*_*oni 7

您必须将模块组合到一个文件中并使它们递归.我不相信有两种方法可以从两个单独文件的编译过程中做到这一点.

module rec A : 
    sig
        val f : int -> int
        val g : int -> int
    end = 
    struct
        let f x = (B.g x) + 1
        let g x = x + 1
    end
and B :
    sig
        val f : int -> int
        val g : int -> int
    end = 
    struct
        let f x = (A.g x) + 1
        let g x = x + 1
    end
Run Code Online (Sandbox Code Playgroud)

编辑:从您的评论,我猜你有解析器的类型定义和处理/操作同一文件中的类型的函数.我同意你的观点,这是有道理的.但是,就像你曾经历过的那样,如果该文件不仅仅是对类型进行操作而是调用解析器来生成数据,那么解析器将如何构建它呢?我的解决方案是将类型分成它自己的模块,并在执行操作的模块中打开该模块.

因此,您将拆分A为(AA'),其中A'包含由其生成B和使用的类型A.你的依赖关系成了,

  • A需要A'BC
  • B 需求 A'

例如,我有一个解析器用于配置文件,我用它来启动我编写的任何应用程序.

ConfType   --contains the type t  
Conf       --calls parser, and contains helper functions for type ConfType.t  
ConfParser --for ocamlyacc
ConfLexer  --for ocamllex
Run Code Online (Sandbox Code Playgroud)

所有这些的替代方案是使用多态变体.通过这种方式,您可以删除依赖项,因为它们是临时定义的.当然,解析器生成的类型可能与Conf中的类型不同,编译器无法帮助您解决错误.