mli文件的模块别名

问题描述 投票:1回答:2

我有以下情况:

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文件的说明。

module ocaml alias
2个回答
3
投票

type t = A | B文件中的m.mlmodule 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,一个实现文件中。


2
投票

你错了的路线是

module D = Ds

在这里,您试图将模块类型“影响”到模块,这不会发生。

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

module type D = module type of Ds
© www.soinside.com 2019 - 2024. All rights reserved.