为什么 OCaml 中的模块类型注释会导致此代码无法编译?

aja*_*112 4 ocaml dictionary module standard-library

我正在使用 OCaml 中的地图模块。考虑以下代码来创建一个以整数为键的映射:

module Int = struct
    type t = int
    let compare a b = a - b
end
 
module IntMap = Map.Make(Int)

let m = IntMap.(empty |> add 3 "hello")
Run Code Online (Sandbox Code Playgroud)

这一切都很好。它的编译和行为符合我的预期。

但是,如果我为模块添加类型注释,Int那么顶行将变为:

module Int : Map.OrderedType = struct
Run Code Online (Sandbox Code Playgroud)

最后一行导致编译错误:

let m = IntMap.(empty |> add 3 "hello")
                             ^
Error: This expression has type int but an expression was expected of type
         IntMap.key = Int.t
Run Code Online (Sandbox Code Playgroud)

然而IntMap.keyInt.t都只是 的别名int。此外,该Int模块的类型为Map.OrderedType。我知道这一点是因为这是Map.Make.

那么地球上正在发生什么呢?为什么提供不必要的类型注释会导致这样的错误。类型注释是否会导致更严格的可访问性并且其行为与推断类型不同?

Jef*_*eld 5

这种注释严格限制了模块的接口。因此,在我看来,通过添加注释,有关映射键类型的唯一已知信息由以下给出Map.OrderedType

module type OrderedType =
    sig type t val compare : t -> t -> int end
Run Code Online (Sandbox Code Playgroud)

t除了它存在并且它出现在 的参数中之外,这并没有说明该类型compare。换句话说,您隐藏了类型t(也称为IntMap.key)与 类型相同的事实int

您可以使用以下命令重新引入这一事实with

module Int : Map.OrderedType with type t = int = struct
    type t = int
    let compare a b = a - b
end
Run Code Online (Sandbox Code Playgroud)