mli文件的模块别名

时间:2017-09-06 17:16:54

标签: 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文件?

备注:我知道实现和接口文件之间的区别,但据我所知,只要接口只包含类型定义,就不需要实现文件。假设我们将以下模块签名添加到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文件的评论。

2 个答案:

答案 0 :(得分:3)

type t = A | B 文件m.ml内的文件基本相同 module M = struct type t = A | B end。 文件m.mli中的同一行对应于 module M : sig type t = A | B end 前者实现了一个模块。后者只是一个模块签名。

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

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

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

答案 1 :(得分:2)

你弄错了这一行是

module D = Ds

在这里,你试图"影响"模块的模块类型,并且不会发生。

但是,您可以对模块类型执行相同的操作:

module type D = module type of Ds