2013-06-18 11 views
6

Obecnie próbuję wykonać przetwarzanie strony mahjong w OCaml i od samego początku napotykam na coś, co mnie trapi.Typy i podtypy uporządkowanych w OCaml

Podam wam przykłady oparte na kartach, ponieważ nie chcę nikogo mylić z terminologią mahjonga.

Podobnie jak w tym , chcę użyć typów wariantów do opisu kolorów, kart i wszystkiego.

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 

I byłoby naprawdę miło, gdyby można napisać funkcję inteligentnej compare że zrozumie uporządkowaną wariant typy.

Idealnie chciałbym napisać coś takiego:

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 

Tak, że kiedy robię

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

daje mi

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

niestety, powraca ocaml Toplevel

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

(która jest już dość dobre!)

Zasadniczo chcę compare funkcję, która weźmie wskazówek ze struktury deklaracji typu.

Przeczytałem ten article on polymorphic compare i this similar question, ale nie jestem pewien, czy chcę polegać na compare_val.

Czy muszę napisać własną funkcję porównywania? Jeśli polecisz mi napisać, czy masz wskazówki na temat sposobu, w jaki należy je napisać, szczególnie w celu zmniejszenia liczby przypadków?

P.S .: Właśnie słyszałem o deriving(Ord) w Haskell ... może być za mało dla mnie do podjęcia skok ...

+0

Uwielbiam Haskella, ale nie skakałbym statkiem po OCaml tylko po cukier "czerpiący". Specjalnie dla typu tego małego. – jozefg

+0

również byłoby miło, gdyby Num mógł być ograniczony od 1..10 – aneccodeal

+1

@ kod, tak, pewnego dnia otrzymamy typy zależne w głównym języku. – paob

Odpowiedz

8

Tak trzeba. Możesz jednak pominąć miejsce, w którym polimorficzne porównanie pasuje do Twoich potrzeb. Na przykład nie musisz pisać porównania dla koloru.

Pochodzenie Haskella (Ord) jest takie samo jak porównanie polimorficzne: jeśli możesz uporządkować konstruktory w porządku w swoim umyśle, możesz wyprowadzić funkcję porównania. Ale jest mocniejszy, ponieważ możesz komponować automatyczne i niestandardowe funkcje porównania. Polimorficzne porównanie OCamla nie może tego zrobić. Na przykład,

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

Jeśli polimorficzny porównanie porządek konstruktora A, B i C odpowiada z konieczności, nie można go używać do porównywania t2, ponieważ nie można nazwać porównanie niestandardową t. Tak więc w tym przypadku, gdybym był tobą, napisałbym test porównawczy2 ręcznie. Również dla twojego przykładu z kartami, łatwo to zrobić za 3 minuty.

Jeśli twoje typy danych są ogromne i bardzo trudno jest zapisać całe porównanie ręcznie, możesz automatycznie wygenerować funkcje porównania z definicji typu przy użyciu CamlP4 i type_conv, tak jak robi to wyprowadzenie (Ord). Ale obawiam się, że nie ma modułu type_conv, który zapewnia jeszcze coś podobnego Ordowi. Osobiście nigdy nie odczuwałem takiej potrzeby.To powinno być miłym ćwiczeniem dla uczniów P4.

+0

Dziękuję za odpowiedź! Myślę, że spróbuję napisać "porównaj" dla każdego typu. A jeśli kod jest naprawdę zbyt rozdęty, przyjrzę się CamlP4. – paob

+0

Jeśli nie znasz jeszcze P4, ostrzegam Cię, powinieneś się spodziewać tego miesiąca :-) – camlspotter

+0

cóż, to tylko projekt zabawkowy bez terminu, więc czemu nie =) – paob