types - 为什么这个 OCaml 仿函数不能识别结构类型?
问题描述
我编写了以下仿函数和实例,
module type Set = sig
type elt
type t
val empty : t
val insert : elt -> t -> t
val find : elt -> t -> bool
end
module type OrderedSet = sig
type t
val compare : t -> t -> int
end
module BstSet(M: OrderedSet) : Set = struct
type elt = M.t
type t = M.t tree
let empty = Leaf
let rec insert x tr = match tr with
| Leaf -> Node(Leaf, x, Leaf)
| Node (lt, y, rt) -> let c = M.compare x y in
if c < 0 then Node (insert x lt, y, rt)
else if c > 0 then Node (lt, y, insert x rt)
else Node (lt, y, rt)
let rec find x tr = match tr with
| Leaf -> false
| Node (lt, y, rt) -> let c = M.compare x y in
if c = 0 then true
else if c < 0 then find x lt
else find x rt
end
module MyString : OrderedSet = struct
type t = string
let compare s1 s2 = compare s1 s2
end
module StringSet = BstSet(MyString);;
StringSet.empty |> StringSet.insert "abc";;
并且编译器引发错误
StringSet.empty |> StringSet.insert "abc";;
^^^^^
Error: This expression has type string but an expression was expected of type
StringSet.elt = BstSet(MyString).elt
Command exited with code 2.
这让我很困惑,因为我原以为编译器会发生这样的事情:
- 我们
BstSet(MyString)
用函子构造,所以参数M
是MyString
。 - 这意味着当我们称之为
M.t
is时string
。 - 这意味着
elt
是string
。 - 这意味着,在 for 的签名中
insert
,我们有一个函数string -> string tree -> string tree
。
所以这应该编译。或者更直接地说,我原以为StringSet.elt
会等于string
。
解决方案
定义
module BstSet(M: OrderedSet) : Set = struct ... end
Set.elt
没有说明and之间的相等性 M.t
(实际上,它们不需要相同,例如,实现可以将额外信息嵌入到 elt 类型中)。要表达这种平等,您必须添加共享约束,例如,
module BstSet(M: OrderedSet) : Set with type elt = M.t = struct ... end
或者,您可以删除模块类型并让编译器查看实现,例如,像这样
module BstSet(M: OrderedSet) = struct ... end
当您不打算从模块中导出仿函数并且仅将其用于内部目的时,这很有用。
推荐阅读
- python - 无法在 pyflakes quickfix 窗口中跳转到行
- javascript - 在 Selenium 中按类打印元素
- html - 使用 css 从 ul li 建表
- google-chrome - Chrome Native Messaging API 是 Chrome 应用程序或 Chrome 扩展程序的一部分
- docker - 如何在两个 docker 容器之间共享一个文件夹内容并允许其中一个删除和写入共享文件夹?
- javascript - 这些特定字母在jquery ui中指的是什么
- mysql - Select MAX in mixed int/string in SQL database
- hashicorp-vault - 使用 Raft 作为存储支持的 Vault HA - 自动加入
- php - 插入与链接表的关系
- r - 循环读取 csv 数据