haskell - 制作 Ord 类的 newtype 实例
问题描述
由于 Ord 是 Eq 的子类,我发现很难理解如何创建该类的新类型实例。
我设法做到了:
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
?
解决方案
在此之后,我应该能够执行以下操作:
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
, given NT1 x > NT1 y
,但当然这并没有真正做任何事情。
好消息是您不需要定义所有这些函数:Haskell 已经在Ord
typeclass 中构造了很多其他函数,所以如果我们查看文档Ord
,我们会看到:
最小完整定义
compare | (<=)
所以实施compare
, or(<=)
就足够了。Haskell 可以基于该实现,还计算其他比较,以及min
,max
等。您可以实现这些,例如,如果有NT1 x < NT1 y
比调用compare
和检查结果是否为 更有效的方法来检查 if 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
参数的名称来实现的。它还在某些不明确的情况下添加了括号(尽管规则有点复杂)。
我们也可以像@DanielWagner 所说的那样自己实现这些功能:
instance Ord NT1 where
compare (NT1 x) (NT1 y) = compare x y
(>) (NT1 x)(NT1 y) = x > y
因此,这里我们不NT1
使用右侧的数据构造函数调用 this ,否则我们将简单地使用相同的参数再次调用此函数。使用上面的实现,我们调用x > y
, 所以(>)
但是在构造函数中包含的参数上。
推荐阅读
- javascript - OAuth2“不允许加载本地资源:chrome-error://chromewebdata/#buttons”
- python - 如何将标签分配给变量的值
- powershell - PowerShell 表单数据输出为 JSON 格式
- regex - 两个标记之间的匹配字符串,这些标记是文件路径并包含特殊字符
- angular - ng 使用特定配置构建
- c - 通过覆盖 %n 生成 root shell 的 Setuid 二进制文件,不适用于漏洞利用,但在不需要漏洞利用时有效
- javafx - 从 TextArea 拖动选定文本时出现 Javafx 问题
- sql - 试图获取所有数据库的相关详细信息
- python - TypeError:“numpy.float64”类型的对象在分配矩阵元素时没有 len()
- python - 如何根据日期合并两个数据框