2013-06-18 36 views
6

我目前正在嘗試在OCaml中進行一些麻將手工處理,並從一開始就直接遇到了一些讓我感到困惑的東西。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的頂層回報

[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) ...可能是足以讓我採取的飛躍......

+0

我喜歡哈斯克爾,但我不會爲了獲取糖而跳上OCaml。特別是對於這種小型的。 – jozefg

+0

如果Num可能受限於1..10 – aneccodeal

+1

@aneccodeal,那麼總有一天我們會在主流語言中獲得依賴類型。 – paob

回答

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從類型定義中自動生成比較函數,就像派生(Ord)一樣。但恐怕沒有type_conv模塊提供Ord之類的東西了。我個人從來沒有覺得有必要擁有它。這對P4學習者來說應該是一個很好的練習。

+0

謝謝你的回答!我想我會嘗試爲每種類型寫'比較'。如果代碼太臃腫,我會看看CamlP4。 – paob

+0

如果你已經不熟悉P4了,我警告過你,你應該期待一個月這個:-) – camlspotter

+0

好吧,這只是一個沒有任何截止日期的玩具項目,爲什麼不=) – paob