OCaml 的ml和mli 文件有什么不同

mli 是类似于java 的interface, 而ml是实现,具体可以参见官方的表格:

文件名和后缀

这是一个在众多OCaml生成平台上使用的标准文件名和后缀名的参考.

源文件和目标文件

与C语言源文件、目标文件和二进制文件的对照:

用途 C 字节码 原生码
源文件 *.c *.ml *.ml
头文件1 *.h *.mli *.mli
目标文件 *.o *.cmo *.cmx2
库文件 *.a *.cma *.cmxa3
二进制程序 prog prog prog.opt4

注释

  1. 在C中,头文件用来描述函数等,但只是一项传统而已。而在OCaml中,*.mli文件用来导出模块的签名(signature),且编译器严格执行它。就拿模块的一个叫Foo的通用例子来说, 你有两个文件: foo.mlfoo.mlifoo.ml 是实现, foo.mli是接口或标签.同时注意,要取得模块名得把文件名的首字母大写.例如, 提扩展库中包括一个名为uTF8.mli 的文件,它是模块UTF8的标签.
  2. 同时存在一个对应的*.o 文件,它包含了实际的机器码,但你通常可以忽略它。
  3. 同时存在一个对应的 *.a文件,它包含了实际的机器码,但你通常可以忽略它。
  4. OCaml程序通常用这个。但事实上, 你可以给这个二进制文件取任意名称.

OCaml 试图强迫您将接口 ( .mli) 与实现 ( .ml. OCaml 强制执行一定数量的抽象(必须发布接口;接口中没有代码)。

对于类型,通常实现与接口相同:两者都声明类型具有特定的表示(并且可能类型声明是生成的)。在这里,不能有抽象,因为实现者没有任何关于他不想发布的类型的信息。(基本上是在声明抽象类型时例外。)

一种看待它的方法是接口已经包含足够的信息来编写实现。给定接口type foobar = Bool of bool | Float of float | Int of int,只有一种可能的实现。所以不要写实现!

一个常见的习惯用法是拥有一个专用于类型声明的模块,并使其只有一个.mli. 由于类型不依赖于值,因此该模块通常在依赖链的早期出现。大多数编译工具都能很好地解决这个问题;例如ocamldep会做正确的事。(与只有 . 相比,这是一个优势.ml。)

这种方法的局限性在于您还需要在这里和那里进行一些模块定义。(一个典型的例子是定义一个类型foo,然后是一个OrderedFoo : Map.OrderedType带有 的模块type t = foo,然后是涉及 的进一步类型声明'a Map.Make(OrderedFoo).t。)这些不能放在接口文件中。有时可以将定义分解为几个块,首先是一堆类型(types1.mli),然后是一个模块(mod1.mlimod1.ml),然后是更多类型(types2.mli)。其他时候(例如,如果定义是递归的),您必须使用.ml没有 a.mli或重复的 a。

您可以让 ocamlc 从 ml 文件中为您生成 mli 文件:

ocamlc -i some.ml > some.mli

分类: 默认 标签: 发布于: 2022-06-21 12:15:15, 更新于: 2022-06-21 12:15:30