制作Ord类的新类型实例

时间:2018-11-12 21:49:27

标签: haskell

由于Ord是Eq的子类,所以我很难理解如何制作该类的newtype实例。

我设法做到了:

    newtype NT1 = NT1 Integer

    instance Eq NT1 where 
        (NT1 x) == (NT1 y) = x == y 

    instance Ord NT1 where 
        (NT1 x) `compare` (NT1 y) = x `compare` y 

如果我有一个变量x = NT1 5和变量y = NT1 5并键入x == y,它将返回True

我也设法做到了:

instance Show NT1 where
        show (NT1 n) = show n

x = NT1 5显示为5而不是NT1 5

在此之后,我应该可以执行以下操作:

instance Ord NT1 where 
       (>)  (NT1 x)(NT1 y)  =  (NT1 x) >   (NT1 y)
       (<)  (NT1 x)(NT1 y)  =  (NT1 x) <   (NT1 y)
       (<=) (NT1 x)(NT1 y)  =  (NT1 x) <=  (NT1 y)
       (>=) (NT1 x)(NT1 y)  =  (NT1 x) >=  (NT1 y)

但这不起作用。我该如何使用Ord类:

class  (Eq a) => Ord a  where
    compare              :: a -> a -> Ordering
    (<), (<=), (>=), (>) :: a -> a -> Bool
    max, min             :: a -> a -> a

1 个答案:

答案 0 :(得分:7)

  

在此之后,我应该能够执行以下操作:

instance Ord NT1 where 
       (>)  (NT1 x)(NT1 y)  =  (NT1 x) >   (NT1 y)
       (<)  (NT1 x)(NT1 y)  =  (NT1 x) <   (NT1 y)
       (<=) (NT1 x)(NT1 y)  =  (NT1 x) <=  (NT1 y)
       (>=) (NT1 x)(NT1 y)  =  (NT1 x) >=  (NT1 y)

您在这里所做的基本上是定义一组函数,每个函数使用 same 参数调用自身,因此这将陷入无限循环。

确实,例如,您在此处定义:

instance Ord NT1 where 
       (>)  (NT1 x)(NT1 y)  =  (NT1 x) >   (NT1 y)

所以这意味着您给定NT1 x > NT1 y的情况下说NT1 x > NT1 y,但当然并没有任何作用。

令人高兴的是,您不需要定义所有这些函数:Haskell已经在Ord类型类中构造了许多其他函数,因此,如果我们看一下{{ 3}},我们看到:

  

最小完整定义

compare | (<=)

因此实现compare(<=)就足够了。 Haskell可以基于该实现,还可以计算其他比较,以及minmax等。您可以实现这些比较,例如,如果有更高的效率,检查NT1 x < NT1 y是否比调用compare并检查结果是否为LT的方法。

您的实现方式如下:

newtype NT1 = NT1 Integer

instance Eq NT1 where 
    (NT1 x) == (NT1 y) = x == y 

instance Ord NT1 where 
    (NT1 x) `compare` (NT1 y) = x `compare` y
因此

就足够了,例如:

Prelude> NT1 14 < NT1 25
True

因此正确地比较了两个对象。

这也是一个简单的实现,如果构造函数相同,则两个NT1对象相等(事实上,这里只有一个 构造函数),并且参数为简单明了的实现。

Ord还有一个“流行”的实现:一个对象被认为小于另一个对象,因为第一个对象的构造函数是在第二个对象的构造函数之前定义的,或者如果两个构造函数相同,通过“按字典顺序”比较这些参数会更小。

Haskell支持这些实现,您可以在类型定义中使用deriving子句:

newtype NT1 = NT1 Integer deriving (Show, Eq, Ord)

因此,这里我们“自动”实现了EqOrdShow类型类。对于Show,其实现方法是先显示构造函数的名称,然后显示参数show。在某些情况下,如果规则含糊不清(尽管规则稍微复杂一些),它也会添加括号。

我们还可以像documentation for Ord一样自己实现以下功能:

instance Ord NT1 where 
    compare (NT1 x) (NT1 y) = compare x y
    (>)  (NT1 x)(NT1 y)  = x > y

因此,在这里我们不使用右侧的NT1数据构造函数进行 not 调用,因为否则我们将再次使用相同的参数再次调用此函数。在上述实现中,我们调用x > y,因此调用(>),但调用包装在构造函数中的自变量