我正在阅读OCaml首席设计师1994年关于模块、类型和独立编译的论文(由Norman Ramsey在另一个问题中向我指出)。我了解到该论文讨论了OCaml当前模块类型/签名系统的起源。其中,作者提出了类型声明在签名中的不透明解释(以允许分别编译),以及具有表现力的显式类型声明。为了演示OCaml模块签名符号试图解决的问题类型,我尝试编写了以下代码:
在文件ordering.ml
(或.mli
- 我都尝试过)中(文件A):
module type ORDERING = sig
type t
val isLess : t -> t -> bool
end
并且在文件useOrdering.ml
中(B文件):
open Ordering
module StringOrdering : ORDERING
let main () =
Printf.printf "%b" StringOrdering.isLess "a" "b"
main ()
这里的想法是期望编译器在编译第二个文件时抱怨模块
StringOrdering
上没有足够的类型信息来对StringOrdering.isLess
应用进行类型检查(从而激发对with type
语法的需求)。然而,尽管文件A按预期编译,但文件B导致3.11.2的ocamlc
抱怨语法错误。我理解签名意味着允许某人基于模块签名编写代码,而无需访问实现(模块结构)。我承认我不确定语法:
module A : B
,我在这篇相当古老的有关分离编译的论文中遇到过它,但这让我想知道是否存在这样或类似的语法(不涉及functor),以允许某人仅基于模块类型编写代码,在链接时提供实际的模块结构,就像在C/C++中可以使用*.h
和*.c
文件一样。如果没有这样的能力,那么模块类型/签名基本上是为了封装/隐藏模块的内部或更明确的类型检查/注释,而不是用于分离/独立编译。
实际上,查看OCaml模块和分离编译手册后,我发现我的类比与C编译单元不符,因为OCaml手册将OCaml编译单元定义为A.ml
和A.mli
二合一,而在C/C++中,.h
文件则被粘贴到任何导入.c
文件的编译单元中。
ocamldep
的输出,它对应于.cmx
文件之间的实际依赖关系,如果您不将它们移动以防止编译器将一个文件中的内容内联到另一个文件中。请注意,该愿望已在“不修复”中解决,而不是“无需更改”。请参见http://frama-c.com/u3cat/download/CuoqICFP09.pdf中的“单独编译”备注。这些从未受到挑战。我很高兴听到OCaml有单独的本地编译,但许多人认为没有。 - Pascal Cuoq