mli 文件的模块别名

标签 module ocaml alias

我有以下情况:

mli 文件 ds.mli 只包含一个类型声明:

type t = A of int | B of string

现在我想在另一个模块 user.ml 中为 Ds 创建一个别名:

module D = Ds

在编译时,我从链接器收到以下错误消息:

$ ocamlc ds.mli user.ml 
File "user.ml", line 1:
Error: Error while linking user.cmo:
Reference to undefined global `Ds'

如果我将 ds.mli 复制到 ds.ml 并调用

 $ ocamlc ds.mli ds.ml user.ml 

编译通过。

是否有可能避免创建 ds.ml 文件?

备注:我知道实现文件和接口(interface)文件之间的区别,但据我所知,只要接口(interface)只包含类型定义,就不需要实现文件。假设我们将以下模块签名添加到 ds.mli:

module T : sig
  type t = C | D
end

然后是用户中bar的定义:

let bar = function
  | Ds.T.C -> true
  | Ds.T.D -> false

通过编译没有问题

$ ocamlc ds.mli user.ml

别名扩展到签名应该不是问题。

编辑: 忘记将 ds.ml 添加到第二个 ocamlc 调用的参数中。 编辑:添加了关于使用 mli 文件的注释。

最佳答案

类型 t = A | B 在文件 m.ml 中基本上与 模块 M = 结构类型 t = A | B 结束。 文件 m.mli 中的同一行对应于 模块 M:信号类型 t = A | B端 前者实现了一个模块。后者只是一个模块签名。

签名可用于声明类型,但更常见的是它用于向外界屏蔽模块实现的某些部分。签名从未实际实现模块,即使模块仅包含类型声明也是如此。

模块就像一个值,而不是一个类型。例如,模块可以作为语言中的值进行包装和操作(“一流模块”),并且可以用作模块语言中仿函数的参数。

功能栏仅适用于存在的 .mli 文件这一事实与此并不矛盾;它是类型上的模式匹配,并且不需要存在类型值来定义函数。如果您在 user 中添加类似 let c = Ds.T.C 的内容,那么您已经构造了这样一个值,但这发生在 user.ml 中,一个实现文件。

关于mli 文件的模块别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46080978/

相关文章:

正则表达式字符间隔有异常

sqlite - 在带有连接表的 sqlite 中执行选择时,别名列具有空值

Python 数学模块显示完全错误的结果?

python - F2PY 找不到模块

ruby - 如何在 Ruby 中初始化模块的实例变量?

python - Windows 上的 "ImportError: No module named site"

generics - 为什么编译器会将两个具有不同名称的等效签名的泛型类型变量识别为不同类型?

haskell - 以下函数是否存在标准名称?

php - 不能在子查询中使用别名

angularjs - 为什么 Angular 中的 ng-controller 使用别名?