简体   繁体   English

如何在 Haskell 中实现代数数据类型的“Ord”?

[英]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 Haskell?在 Haskell 中为这种代数数据类型实例化/实现“Ord”的最佳方法是什么?

The best way would be to just add deriving (Eq, Ord) to the type's definition.最好的方法是将deriving (Eq, Ord)添加到类型的定义中。

Since you listed your constructors in ascending order, the derived Ord instance will give you exactly the order you want.由于您按升序列出了构造函数,因此派生的Ord实例将为您提供所需的确切顺序。

However, if 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.但是,如果由于某种原因无法更改定义中的顺序,您仍然可以导出 Eq,因为顺序无关紧要。 Given an instance of Eq, we can manually write an instance for Ord.给定一个 Eq 的实例,我们可以手动为 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 xy |定义 compare 最简洁的方法可能是拼出 compare 应该返回 LT 的所有组合,然后简单地使用 compare xy | x == y = Eq; x == y = 等式; compare _ _ = GT for the remaining combinations.比较剩余组合的 _ _ = GT。

As has been mention, you can derive Eq and Ord .如前所述,您可以推导出EqOrd Or you could derive Enum and then do或者你可以派生Enum然后做

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

For anyone wondering, here is the complete, explicit, boilerplate implementation:对于任何想知道的人,这里是完整、明确的样板实现:

Using roman numerals.使用罗马数字。
Using case for ease of reading.使用case以方便阅读。

data RN = I | II | III | IV | V

instance Eq RN where
    I == I     = True
    I == _     = False
    II == II   = True
    II == _    = False
    III == III = True
    III == _   = False
    IV == IV   = True
    IV == _    = False
    V == V     = True
    V == _     = False

instance Ord RN where
    compare I x = case x of
        I   -> EQ
        _   -> LT
    compare II x = case x of
        I   -> GT
        II  -> EQ
        _   -> LT
    compare III x = case x of
        I   -> GT
        II  -> GT
        III -> EQ
        _   -> LT
    compare IV x = case x of
        V   -> LT
        IV  -> EQ
        _   -> GT
    compare V x = case x of
        V   -> EQ
        _   -> GT

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

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