2013-06-18 7 views
6

Ich versuche gerade, einige Hands in Mahjong in OCaml zu bearbeiten und bin von Anfang an mit etwas konfrontiert, was mich nervt.Geordnete Variantentypen und Subtypen in OCaml

Ich gebe Ihnen Beispiele basierend auf Karten, weil ich niemanden mit Mahjong-Terminologie verwechseln will.

Genau wie in diesem part on User-Defined Types from OCaml for the Skeptical, möchte ich Variantentypen verwenden, um Anzüge, Karten und alles zu beschreiben.

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 

Und es wäre wirklich schön, wenn ich eine intelligente compare Funktion schreiben könnte, die Variantentypen bestellt verstehen würde.

Im Idealfall würde ich so etwas schreiben:

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 

So dass, wenn ich

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

es gibt mir

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

Ach, die ocaml Toplevel kehrt

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

(die bereits ziemlich gut ist!)

Grundsätzlich möchte ich eine compare Funktion, die Hinweise aus der Typdeklaration Struktur nehmen würde.

Ich habe diese article on polymorphic compare und this similar question gelesen, aber ich bin mir nicht sicher, ob ich mich auf compare_val verlassen möchte.

Muss ich wirklich meine eigene Vergleichsfunktion schreiben? Wenn Sie mir empfehlen, eines zu schreiben, haben Sie Tipps, wie es geschrieben werden sollte, insbesondere um die Anzahl der Fälle zu reduzieren?

P. S .: Ich habe gerade gehört, über deriving(Ord) in Haskell ... Könnte genug für mich, den Sprung zu nehmen ...

+0

Ich liebe Haskell, aber ich würde nicht auf OCaml springen, nur um 'Zucker 'abzuleiten. Vor allem für einen Typ so klein. – jozefg

+0

auch wäre es nett, wenn Num von 1..10 – aneccodeal

+1

@aneccodeal yep eingeschränkt werden könnte, irgendwann werden wir abhängige Typen in einer Mainstream-Sprache bekommen. – paob

Antwort

8

Ja, Sie haben. Aber Sie können überspringen, wo der polymorphe Vergleich mit Ihrem Bedarf übereinstimmt. Zum Beispiel brauchen Sie Ihren Vergleich nicht zu schreiben.

Haskells Ableiten (Ord) ist genauso wie der polymorphe Vergleich: Wenn Sie Konstruktoren in der Reihenfolge in Ihrem Verstand bestellen können, dann können Sie die Vergleichsfunktion ableiten. Aber es ist leistungsfähiger, da Sie automatische und benutzerdefinierte Vergleichsfunktionen erstellen können. Der polymorphe Vergleich von OCaml kann das nicht. Zum Beispiel

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! *) 

Wenn die polymorphe Vergleich Ordnung des Konstruktor A, B und C übereinstimmt mit Ihrem Bedarf, können Sie es nicht zum Vergleich von T2 verwenden, da es nicht den benutzerdefinierten Vergleich zum t aufrufen können. In diesem Fall würde ich compare_t2 von Hand schreiben, wenn ich Sie wäre. Für Ihr Beispiel von Karten ist es leicht in 3 Minuten getan.

Wenn Ihre Datentypen riesig sind und es extrem mühsam ist, alle Vergleiche auf die Hand zu schreiben, können Sie die Vergleichsfunktionen aus der Typdefinition mit CamlP4 und type_conv automatisch generieren, genau wie Ableiten (Ord). Aber ich fürchte, es gibt kein type_conv-Modul, das Ord-ähnliches bietet. Persönlich habe ich nie das Gefühl gehabt, es zu haben.Es sollte eine schöne Übung für P4-Lernende sein.

+0

Vielen Dank für die Antwort! Ich denke, ich werde dann versuchen, für jeden Typ 'compare' zu ​​schreiben. Und wenn der Code wirklich zu aufgebläht ist, werde ich CamlP4 anschauen. – paob

+0

Wenn Sie P4 noch nicht kennen, warne ich Sie, Sie sollten einen Monat dafür erwarten :-) – camlspotter

+0

nun, das ist nur ein Spielzeugprojekt ohne Frist so warum nicht =) – paob