Скажем, у меня есть тип данных, представляющий колода покерных карт, как такКак реализовать пользовательский заказ для типов данных в Haskell?
data Suit = Clubs | Spades | Hearts | Diamonds deriving (Eq)
instance Show Suit where
show Diamonds = "♦"
show Hearts = "♥"
show Spades = "♠"
show Clubs = "♣"
data Value = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King | Ace deriving (Eq, Ord)
data Card = Card {
value :: Value
, suit :: Suit
} deriving (Eq, Ord)
экземпляр Show Card, где шоу (Card против) = показать s ++ показать v
Haskell помогает мне уже много, позвольте мне получить Eq
и Ord
без явного указания этих отношений. Это особенно полезно, потому что я хочу использовать Ord
, чтобы в конечном счете сравнить стоимость двух рук в соответствии с правилами покера.
Теперь в Покере костюмы не имеют особого значения с точки зрения заказа. Поэтому я попытался
instance Ord Suit where
compare Clubs Spades = EQ
compare Clubs Hearts = EQ
compare Clubs Diamonds = EQ
compare Spades Hearts = EQ
compare Spades Diamonds = EQ
compare Hearts Diamonds = EQ
Это уже немного многословным ... и это даже не работает:
*P054> a
♠A
*P054> b
♣A
*P054> a < b
*** Exception: P054.hs:(12,9)-(17,36): Non-exhaustive patterns in function compare
Так как я могу правильно определить порядок на Suit
, что отражает тот факт, что все костюмы равны?
Определение такого экземпляра, вероятно, плохой дизайн. Не так много людей ожидали бы, что экземпляр «Ord» будет определен как 'const (const EQ)'. Если сравнение между Suits не имеет смысла, экземпляр Ord просто не существует. Если костюм не влияет на порядок карты, как сказал OP, то экземпляр Ord для * Card * должен просто игнорировать иск: 'compare = Data.Ord.comparing val' – user2407038
@ user2407038 Я бы принял ваш комментарий в качестве ответа , –
@Zeta Ah ... редактирование. В этом есть смысл :) –