我正在阅读 OCaml lead designer's 1994 paper on modules, types, and separate compilation. (Norman Ramsey 中的 another question 向我指点)。我知道这篇论文讨论了 OCaml 当前模块类型/签名系统的起源。因此,作者建议对签名中的类型声明(以允许单独编译)以及 list 类型声明(为了表达性)进行不透明的解释。尝试整理我自己的一些示例来演示 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
我在 this rather old paper on separate compilation 中遇到的但这让我想知道是否存在这样或类似的语法(不涉及仿函数)以允许某人仅基于模块类型编写代码,并在链接时提供实际模块结构,类似于如何使用 *.h
和 *.c
C/C++ 中的文件。如果没有这种能力,似乎模块类型/签名基本上是用于密封/隐藏模块内部或更明确的类型检查/注释,而不是用于单独/独立编译。实际上,查看 OCaml manual section on modules and separate compilation似乎我与 C 编译单元的类比被打破了,因为 OCaml 手册将 OCaml 编译单元定义为
A.ml
和 A.mli
二重奏,而在 C/C++ 中 .h
文件被粘贴到任何导入的编译单元 .c
文件。
最佳答案
做这样的事情的正确方法是执行以下操作:
(* This define the signature *)
module type ORDERING = sig
type t
val isLess : t -> t -> bool
end
(* This define a module having ORDERING as signature *)
module StringOrdering : ORDERING
ocamlc -c ordering.mli
open Ordering
let main () =
Printf.printf "%b" (StringOrdering.isLess "a" "b")
let () = main ()
编译文件时,您会收到预期的类型错误(即
string
与 Ordering.StringOrdering.t
不兼容)。如果要删除类型错误,应添加 with type t = string
对 StringOrdering
定义的约束在 ordering.mli
. 所以回答你的第二个问题:是的,在字节码模式下,编译器只需要知道你所依赖的接口(interface),你可以选择在链接时使用哪个实现。默认情况下, native 代码编译并非如此(因为模块间优化),但您可以禁用它。
关于module - OCaml 模块类型和单独编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9843378/