开发者

How to implement "Ord" for algebraic data types in Haskell?

Imagine you have a rating like

Rating = OneStar | TwoStars | ThreeStars | FourStars | FiveStars

What is the best way to instanciate/implement "Ord" for such an algebraic data type in Has开发者_JAVA技巧kell?


The best way would be to just add deriving (Eq, Ord) to the type's definition.

Since you listed your constructors in ascending order, the derived Ord instance will give you exactly the order you want.

However, when the order of definitions does not match the comparison order you want and changing the order in the definition is not an option for some reason, you can still derive Eq, since for that the order does not matter. Given an instance of Eq, we can manually write an instance for Ord. The most succinct way to define compare would probably be to spell out all the combinations for which compare should return LT and then simply use compare x y | x == y = Eq; compare _ _ = GT for the remaining combinations.


As has been mention, you can derive Eq and Ord. Or you could derive Enum and then do

instance Eq Rating where
    x == y = fromEnum x == fromEnum y

Or just spell it all out

instance Eq Rating where
    OneStar == OneStar = True
    TwoStar == TwoStar = True
...
    _ == _ = False


Another way to implement compare is to fall back on a type that already is an instance of Ord.

data Rating = OneStar | TwoStars | ThreeStars | FourStars | FiveStars
    deriving (Show, Eq)

instance Ord Rating where
  compare x y = compare (r2n x) (r2n y)
    where
      r2n OneStar = 1
      r2n TwoStars = 2
      r2n ThreeStars = 3
      r2n FourStars = 4
      r2n FiveStars = 5

This solution scales pretty well, I think.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜