OCaml中的有序变体类型和子类型

时间:2013-06-18 15:38:03

标签: haskell compare ocaml algebraic-data-types

我目前正在尝试在OCaml中进行一些麻将手处理,并且从一开始我就遇到了一些让我烦恼的事情。

我会给你一些基于卡片的例子,因为我不想让任何人混淆麻将术语。

就像在这个part on User-Defined Types from OCaml for the Skeptical中一样,我想使用变体类型来描述套装,卡片以及所有内容。

type suit = Club | Diamond |  Heart | Spade
type value = Jack | Queen | King | Ace | Num of int
type card = Card of suit * value | Joker
type hand = card list

如果我能编写一个能理解有序变体类型的智能compare函数,那将是非常好的。

理想情况下,我会写出类似的东西:

type suit = Club < Diamond <  Heart < Spade
type value = Num of int < Jack < Queen < King < Ace
type card = Card of suit * value < Joker
type hand = card list

所以当我这样做时

List.sort Pervasives.compare [Card(Diamond, Num 3); Joker; Card(Spade, Ace); Card(Diamond, Num 2)]

它给了我

[Card(Diamond, Num 2); Card(Diamond, Num 3); Card(Spade, Ace); Joker]

唉,ocaml toplevel返回

[Joker; Card(Spade, Ace); Card(Diamond, Num 2); Card(Diamond, Num 3)]

(已经相当不错!)

基本上我想要一个compare函数,它将从类型声明结构中获取提示。

我已阅读此article on polymorphic comparethis similar question,但我不确定是否要依赖compare_val

我真的必须编写自己的比较功能吗?如果你建议我写一个,你有关于它应该写的方式的提示,特别是减少案件的数量?

P.S。:我刚刚在Haskell听说过deriving(Ord) ......可能足以让我跳起来......

2 个答案:

答案 0 :(得分:8)

是的,你必须这样做。但是你可以跳过多态比较符合你需要的地方。例如,您不需要为套装编写比较。

Haskell的派生(Ord)与多态比较相同:如果您可以在脑海中按顺序排序构造函数,那么您可以派生比较函数。但它更强大,因为您可以编写自动和自定义比较功能。 OCaml的多态比较不能做到这一点。例如,

type t = ...
let compare_t = .... (* custom comparison for t *)
type t2 = A of t | B of t | C of t (* I want to write a comparion for t2 now! *)

如果构造函数A,B和C的多态比较顺序与您的需要匹配,则不能将其用于比较t2,因为它无法调用t的自定义比较。所以在这种情况下,如果我是你,我会手工编写compare_t2。对于你的卡片例子,它很容易在3分钟内完成。

如果您的数据类型很大并且用手写下所有比较非常痛苦,您可以使用CamlP4和type_conv从类型定义中自动生成比较函数,就像derinding(Ord)一样。但是我担心没有type_conv模块可以提供类似Ord的东西。我个人从来没有觉得有必要。这对P4学习者来说应该是一个很好的练习。

答案 1 :(得分:1)

我已经晚了7年,但是您可以使用ppx_deriving实现这一目标:

type value = Num of int | Jack | Queen | King | Ace [@@deriving ord]
type suit = Club | Diamond | Heart | Spade [@@deriving ord]
type card = Card of suit * value | Joker [@@deriving ord]
type hand = card list

使用ocamlfind ocamlopt -o executable.out -linkpkg -package ppx_deriving.ord file.ml链接程序包。