pao*_*aob 6 ocaml haskell compare algebraic-data-types
我目前正在尝试在OCaml中进行一些麻将手处理,并且从一开始我就遇到了一些让我烦恼的事情.
我会给你一些基于卡片的例子,因为我不想把任何人混淆麻将术语.
就像在OCaml中针对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
Run Code Online (Sandbox Code Playgroud)
如果我能编写一个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
Run Code Online (Sandbox Code Playgroud)
所以,当我这样做
List.sort Pervasives.compare [Card(Diamond, Num 3); Joker; Card(Spade, Ace); Card(Diamond, Num 2)]
Run Code Online (Sandbox Code Playgroud)
它给了我
[Card(Diamond, Num 2); Card(Diamond, Num 3); Card(Spade, Ace); Joker]
Run Code Online (Sandbox Code Playgroud)
唉,ocaml toplevel返回
[Joker; Card(Spade, Ace); Card(Diamond, Num 2); Card(Diamond, Num 3)]
Run Code Online (Sandbox Code Playgroud)
(已经相当不错!)
基本上我想要一个compare从类型声明结构中获取提示的函数.
我已经读过这篇关于多态比较和类似问题的文章,但我不确定我是否想要依赖compare_val.
Do I really have to write my own compare function? If you recommend me to write one, do you have tips on the way it should be written, especially to reduce the number of cases?
P.S.: I just heard about deriving(Ord) in Haskell... Might be enough for me to take the leap...
是的,你必须.但是你可以跳过多态比较符合你需要的地方.例如,您不需要为西装编写比较.
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! *)
Run Code Online (Sandbox Code Playgroud)
如果构造函数A,B和C的多态比较顺序与您的需要匹配,则不能将其用于比较t2,因为它无法调用t的自定义比较.所以在这种情况下,如果我是你,我会手工编写compare_t2.对于您的卡片示例,它可以在3分钟内轻松完成.
如果您的数据类型很大并且用手写下所有比较非常痛苦,您可以使用CamlP4和type_conv从类型定义自动生成比较函数,就像derinding(Ord)一样.但是我担心没有type_conv模块可以提供类似Ord的东西.我个人从来没有觉得有必要.这对P4学习者来说应该是一个很好的练习.