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



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

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")

这一切都很好。它的编译和行为正如我所期望的那样。

但是,如果我为Int模块添加一个类型注释,那么最上面的一行变成:

module Int : Map.OrderedType = struct

最后一行导致编译错误:

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

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

那么,这里到底发生了什么?为什么提供一个不必要的类型注释会导致这样的错误。类型注释是否会导致更严格的可访问性,并且行为与推断类型不同?

这种注释严格限制了模块的接口。因此,在我看来,添加了注释后,关于映射的密钥类型,已知的只有Map.OrderedType:给出的内容

module type OrderedType =
sig type t val compare : t -> t -> int end

这并没有说明类型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

相关内容

  • 没有找到相关文章

最新更新