简体   繁体   中英

Making a custom datatype ord-able

Can someone explain to me how do I make a custom data type ord-able?

** I'm not allowed to make modifications to Suit itself, eg. deriving (Eq, Ord)

data Suit = Clubs | Diamonds | Hearts | Spades deriving (Eq)

My Attempt:

instance Ord Suit where
    compare suit1 suit2 = compare suit1 suit2

but that seems to go on a continuous loop and doesn't halt.

The definition of Ord looks something like (but not quite)

class Ord a where
    compare :: a -> a -> Ordering

and Ordering has three possible values: LT, EQ, GT .

So, you need to define what the result of each comparison should be. Something like:

instance Ord Suit where
    compare Clubs Diamonds    = LT
    compare Diamonds Clubs    = GT
    compare Diamonds Diamonds = EQ
    compare Diamonds _        = LT -- Diamonds are lower than everything besides Clubs and Diamonds

Your actual ordering may be different, but that should give you the basic idea.

You can use standalone deriving with the same effect.

deriving instance Enum Suit
deriving instance Ord Suit

A way to write a custom Ord instance where you don't have to spell out the result of each comparison is:

instance Ord Suit where
    compare a b = compare (relativeRank a) (relativeRank b) where
         relativeRank Diamonds = 1
         relativeRank Clubs = 2
         relativeRank Hearts = 3
         relativeRank Spades = 4

Here, you only need to mention each constructor once, and you can easily decide on a different ordering.

You can just as well use compare Data.Function.on relativeRank , but this is maybe easier to understand.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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