比较对所有类型都有效吗?
Does compare work for all types?
让我们考虑一个类型 t
和两个 t
类型的变量 x,y
。
调用 compare x y
是否对任何类型都有效 t
?我找不到任何反例。
它不适用于函数类型:
# 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. *)
Pervasives
中 compare
的 documentation 中也列出了这些案例。
多态 compare 函数通过递归探索值的结构来工作,提供 OCaml 值的 ad-hoc 总排序,用于定义 结构等式 由多态 = 运算符测试。
按照@antron 的观察,它在设计上并未在函数和闭包上定义。定义的递归性质意味着结构相等性没有在包含函数或闭包的值上定义。这种递归性质还意味着 compare 函数未在递归值上定义,正如 @antron 所提到的那样。
结构相等,因此 compare 函数和比较运算符不知道结构不变量,不能用于比较(温和的)高级数据结构,例如集合,地图、哈希表等。如果需要对这些结构进行比较,则必须编写专门的函数,这就是为什么 Set 和 Map 定义了这样的函数。
定义您自己的结构时,一个好的经验法则是区分
具体类型,仅根据原始类型和其他具体类型定义。具体类型不应该用于处理需要某些不变量的结构,因为很容易创建这种类型的任意值来破坏这些不变量。对于这些类型,多态比较函数和运算符是合适的。
抽象类型,具体定义隐藏。对于这些类型,最好提供专门的比较函数。 mixture library defines a compare mixin that can be used to derive comparison operators from the implementation of a specialised compare function. Its use is illustrated in the README.
让我们考虑一个类型 t
和两个 t
类型的变量 x,y
。
调用 compare x y
是否对任何类型都有效 t
?我找不到任何反例。
它不适用于函数类型:
# 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. *)
Pervasives
中 compare
的 documentation 中也列出了这些案例。
多态 compare 函数通过递归探索值的结构来工作,提供 OCaml 值的 ad-hoc 总排序,用于定义 结构等式 由多态 = 运算符测试。
按照@antron 的观察,它在设计上并未在函数和闭包上定义。定义的递归性质意味着结构相等性没有在包含函数或闭包的值上定义。这种递归性质还意味着 compare 函数未在递归值上定义,正如 @antron 所提到的那样。
结构相等,因此 compare 函数和比较运算符不知道结构不变量,不能用于比较(温和的)高级数据结构,例如集合,地图、哈希表等。如果需要对这些结构进行比较,则必须编写专门的函数,这就是为什么 Set 和 Map 定义了这样的函数。
定义您自己的结构时,一个好的经验法则是区分
具体类型,仅根据原始类型和其他具体类型定义。具体类型不应该用于处理需要某些不变量的结构,因为很容易创建这种类型的任意值来破坏这些不变量。对于这些类型,多态比较函数和运算符是合适的。
抽象类型,具体定义隐藏。对于这些类型,最好提供专门的比较函数。 mixture library defines a compare mixin that can be used to derive comparison operators from the implementation of a specialised compare function. Its use is illustrated in the README.