OCaml模块类型和单独编译

Mar*_*tus 8 ocaml module

我正在阅读OCaml首席设计师1994年关于模块,类型和单独编译的论文.(诺曼拉姆齐另一个问题中向我指出).据我所知,本文讨论了OCaml目前的模块类型/签名系统的起源.在此,作者提出了对签名中类型声明的不透明解释(允许单独编译)以及清单类型声明(表达性).试图将我自己的一些示例放在一起来演示OCaml模块签名符号试图解决的问题,我在两个文件中编写了以下代码:

在文件中ordering.ml(或.mli- 我已经尝试过)(文件A):

module type ORDERING = sig
 type t
 val isLess : t -> t -> bool
end
Run Code Online (Sandbox Code Playgroud)

并在文件useOrdering.ml(文件B)中:

open Ordering
module StringOrdering : ORDERING
  let main () =
    Printf.printf "%b" StringOrdering.isLess "a" "b"
  main ()
Run Code Online (Sandbox Code Playgroud)

想法是期望编译器抱怨(在编译第二个文件时)模块上没有足够的类型信息StringOrdering来检查StringOrdering.isLess应用程序(从而激发对with type语法的需求).但是,尽管文件A按预期编译,但文件B导致3.11.2 ocamlc抱怨语法错误.我知道签名的目的是允许某人根据模块签名编写代码,而无需访问实现(模块结构).

我承认我不确定语法:module A : B我在这篇相当旧的论文中遇到的单独编译,但它让我想知道是否存在这样或类似的语法(不涉及仿函数)以允许某人仅根据模块类型编写代码,在链接时提供的实际模块结构,类似于人们如何在C/C++中使用*.h*.c文件.没有这样的能力,似乎模块类型/签名基本上用于密封/隐藏模块的内部或更明确的类型检查/注释,但不用于单独/独立的编译.

实际上,看看关于模块和单独编译OCaml手册部分,似乎我对C编译单元的类比被打破了,因为OCaml手册将OCaml编译单元定义为A.mlA.mli二重奏,而在C/C++中,.h文件被粘贴到任何导入.c文件的编译单元.

Tho*_*mas 6

做这样的事情的正确方法是执行以下操作:

  1. 在ordering.mli写道:

    (* 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
    
    Run Code Online (Sandbox Code Playgroud)
  2. 编译文件: ocamlc -c ordering.mli

  3. 在另一个文件中,请参阅编译的签名:

    open Ordering
    
    let main () =
      Printf.printf "%b" (StringOrdering.isLess "a" "b")
    
    let () = main ()
    
    Run Code Online (Sandbox Code Playgroud)

    编译文件时,会得到预期的类型错误(即string不兼容Ordering.StringOrdering.t).如果要删除类型错误,则应将with type t = string约束添加到StringOrderingin 的定义中ordering.mli.

所以回答第二个问题:是的,在字节码模式下,编译器只需要知道你所依赖的接口,你可以选择在链接时使用哪个实现.默认情况下,本地代码编译不适用(因为模块间优化),但您可以禁用它.