ocamlc -i some.ml > some.mli
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 |
注释
- 在C中,头文件用来描述函数等,但只是一项传统而已。而在OCaml中,
*.mli
文件用来导出模块的签名(signature),且编译器严格执行它。就拿模块的一个叫Foo
的通用例子来说, 你有两个文件:foo.ml
和foo.mli
。foo.ml
是实现,foo.mli
是接口或标签.同时注意,要取得模块名得把文件名的首字母大写.例如, 提扩展库中包括一个名为uTF8.mli
的文件,它是模块UTF8
的标签. - 同时存在一个对应的*.o 文件,它包含了实际的机器码,但你通常可以忽略它。
- 同时存在一个对应的 *.a文件,它包含了实际的机器码,但你通常可以忽略它。
- 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.mli
和mod1.ml
),然后是更多类型(types2.mli
)。其他时候(例如,如果定义是递归的),您必须使用.ml
没有 a.mli
或重复的 a。
您可以让 ocamlc 从 ml 文件中为您生成 mli 文件:
分类: 默认 标签: 发布于: 2022-06-21 12:15:15, 更新于: 2022-06-21 12:15:30