作者:小米-发烧友 | 来源:互联网 | 2022-11-30 09:26
由于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
whill显示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> Willem Van O..:
在此之后,我应该能够做到这样的事情:
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)
你在这里做的基本上是定义一组函数,其中每个函数调用自身,具有相同的参数,因此这将陷入无限循环.
实际上,例如你在这里定义:
instance Ord NT1 where
(>) (NT1 x)(NT1 y) = (NT1 x) > (NT1 y)
所以这意味着你说NT1 x > NT1 y
,给予NT1 x > NT1 y
,但当然,这并没有真正做任何事情.
好处是你不需要定义所有这些函数:Haskell已经在Ord
类型类中构建了许多其他函数,所以如果我们看一下文档Ord
,我们会看到:
最小的完整定义
compare | (<=)
所以实施compare
,或者(<=)
就足够了.哈斯克尔可以基于该实现,也计算其他的比较,以及min
,max
等你能实现这些,例如,如果有更有效的方法来检查,如果NT1 x 不是调用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
如果构造函数是相同的两个对象是相同的(这里只有一个构造函数),并且参数是一个简单的实现.
Ord
还有一个"流行的"实现:一个对象被认为小于另一个对象,因为第一个对象的构造函数是在第二个对象的构造函数之前定义的,或者如果构造函数是相同的,那么通过比较这些参数,参数会更小"按字典顺序".
Haskell支持这些类型的实现,您可以deriving
在类型定义中使用子句:
newtype NT1 = NT1 Integer deriving (Show, Eq, Ord)
在这里,我们因此"自动"执行Eq
,Ord
和Show
类型类.因为Show
它是通过首先显示构造函数的名称,后跟show
参数的名称来实现的.它还在某些情况下添加了括号(尽管规则稍微复杂一些).
我们也可以像@DanielWagner所说的那样自己实现这些功能:
instance Ord NT1 where
compare (NT1 x) (NT1 y) = compare x y
(>) (NT1 x)(NT1 y) = x > y
在这里,我们这样做不是与调用该NT1
右侧数据构造,因为否则我们就简单地同样具有相同的参数调用此函数.通过上面的实现,我们调用x > y
,(>)
但是在构造函数中包含的参数.
...如果你真的想要出于任何原因自己实现所有`Ord`方法,你可以`(>)(NT x)(NT y)=(>)xy`(右边没有`NT`包装器).或者,按照预期的方式使用中缀符号,`NT x> NT y = x> y`.