我们考虑t
类型和x,y
类型的两个变量t
。
电话compare x y
对任何类型t
都有效吗?我无法找到任何反例。
答案 0 :(得分:7)
多态比较函数通过递归地探索值的结构来工作,提供OCaml值的临时总排序,用于定义由多态性测试的结构相等 = 运营商。
按照设计,它没有在函数和闭包上定义,正如@antron所观察到的那样。定义的递归性质意味着结构相等性不是在包含函数或闭包的值上定义的。这种递归性质也意味着 compare 函数没有在递归值上定义,如@antron所提到的那样。
结构相等,因此比较函数和比较运算符,不知道结构不变量,也不能用于比较(温和)高级数据结构,如集合,映射,HashTbls等上。如果需要比较这些结构,必须编写一个专门的函数,这就是Set和Map定义这样一个函数的原因。
在定义自己的结构时,一个好的经验法则是区分
具体类型,仅根据基本类型和其他具体类型定义。具体类型不应该用于处理期望一些不变量的结构,因为很容易创建这种类型的任意值来破坏这些不变量。对于这些类型,多态比较函数和运算符是合适的。
抽象类型,其具体定义是隐藏的。对于这些类型,最好提供专门的比较功能。 mixture library定义了compare mixin,可用于从专门的 compare 函数的实现中派生比较运算符。其用途在README。
答案 1 :(得分:6)
它不适用于函数类型:
# compare (fun x -> x) (fun x -> x);;
Exception: Invalid_argument "equal: functional value".
同样,它(通常)不适用于其值可以包含函数的其他类型:
# type t = A | B of (int -> int);;
type t = A | B of (int -> int)
# compare A A;;
- : int = 0
# compare (B (fun x -> x)) A;;
- : int = 1
# compare (B (fun x -> x)) (B (fun x -> x));;
Exception: Invalid_argument "equal: functional value".
它也(通常)不适用于递归值:
# type t = {self : t};;
type t = { self : t; }
# let rec v = {self = v};;
val v : t = {self = <cycle>}
# let rec v' = {self = v'};;
val v' : t = {self = <cycle>}
# compare v v;;
- : int = 0
# compare v v';;
(* Does not terminate. *)
这些案例也列在compare
Pervasives
的{{1}}中。