简体   繁体   English

如何在Haskell中实现数据类型的自定义排序?

[英]How to implement custom ordering for data types in Haskell?

Let's say I have a data type that represents a deck of poker cards like so 假设我有一个数据类型,表示像这样的一副扑克牌

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)

instance Show Card where show (Card vs) = show s ++ show v 实例Show Card,其中show(Card vs)= show s ++ show v

Haskell helps me already a lot by allow me to derive Eq and Ord without explicitly specifying those relations. Haskell通过允许我导出EqOrd而无需明确指定这些关系,已经对我有很大帮助。 This is especially useful, because I want to use Ord to ultimately compare the value of two hands according to Poker rules. 这特别有用,因为我想使用Ord根据扑克规则最终比较两只手的价值。

Now in Poker, the suits do not really matter in terms of ordering. 现在在扑克中,西装的顺序实际上并不重要。 Therefore I tried 因此我尝试了

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

This is already a bit verbose ... and it does not even work: 这已经有点冗长了……甚至不起作用:

*P054> a
♠A
*P054> b
♣A
*P054> a < b
*** Exception: P054.hs:(12,9)-(17,36): Non-exhaustive patterns in function compare

So how can I properly define an ordering on Suit that expresses the fact that all suits are equal? 那么,如何在Suit上正确定义一个顺序,以表达所有西服都相等的事实呢?

You are missing several combinations, eg all with Clubs on the right hand side. 你缺少几个组合,比如所有Clubs在右手边。 If all are equal, what are the possible results of compare , regardless of the input? 如果所有条件相等,那么不管输入什么, compare的可能结果是什么? There is only one: EQ . 只有一个: EQ Therefore we don't even need to look at a or b : 因此,我们甚至不需要查看ab

instance Ord Suit where
    compare _ _ = EQ

However, that Ord instance is rather useless. 但是,该Ord实例却毫无用处。 Alternatively you can create a custom instance for Card , 或者,您可以为Card创建自定义实例,

instance Ord Card where
    compare a b = compare (value a) (value b)
    -- compare = compare `on` value -- using `on` from Data.Function
    -- compare = comparing value    -- using `comparing` from Data.Ord

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM