由于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
?
答案 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可以基于该实现,还可以计算其他比较,以及min
,max
等。您可以实现这些比较,例如,如果有更高的效率,检查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)
因此,这里我们“自动”实现了Eq
,Ord
和Show
类型类。对于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
,因此调用(>)
,但调用包装在构造函数中的自变量。