我对Haskell很新,我不明白为什么我无法比较这两个变量。 我有这个功能:
nextMinute :: Date -> Time -> DateTime
nextMinute date time = if time == Time 23 59
then DateTime (tomorrow date) newDay
else DateTime date (timeSucc time)
我收到此错误消息:
Time.hs:88:32:
No instance for (Eq Time) arising from a use of ‘==’
In the expression: time == Time 23 59
In the expression:
if time == Time 23 59 then
DateTime date newDay
else
DateTime date (timeSucc time)
In an equation for ‘nextMinute’:
nextMinute date time
= if time == Time 23 59 then
DateTime date newDay
else
DateTime date (timeSucc time)
答案 0 :(得分:6)
您可以只使用模式匹配来代替使用==
:
nextMinute :: Date -> Time -> DateTime
nextMinute date (Time 23 59) = DateTime (tomorrow date) newDay
nextMinute date time = DateTime date (timeSucc time)
将Eq
添加到Time
类型可能很好,但是当模式匹配的解决方案同样出色时,也没有特别需要。
答案 1 :(得分:5)
平等比较在Haskell中有点代码味道。如果您发现自己使用它,请始终考虑是否应该更好地使用模式匹配,如amalloy的答案所示。模式匹配往往更有效,并且即使在完全不可能的情况下(例如在无限长度列表上†),通常仍然有效。
除此之外,IMO还有一些类型,你应该更好地避免任何平等假设。这包括代表一些连续物理量的所有类型,例如确实是时间。从数学上讲,两个这样的值是effectively never equal。从更实际的角度来看,您的方法存在这样的风险:如果您以某种方式超过确切的值23:59
(例如,在检查日期转换之前添加一分钟和第二个),那么换行将永远不会发生!
因此,我建议仅将这些值与较少/较大的运算符进行比较。
nextMinute :: Date -> Time -> DateTime
nextMinute date time
| h' >= 24 = DateTime (tomorrow date) newDay
| otherwise = DateTime date naïveSucc
where naïveSucc@(Time h' _) = timeSucc time
† 事实上,无限长列表上的等式与实数上的等式有很多相同的问题,如果你将它们描述为无限长度的十进制扩展。当然,我们通常使用的数字类型实际上并不是无限精确的,但奇怪的是它常常有助于假装:真的,浮点数会受到各种令人讨厌的不确定性问题的影响,但如果你只是不喜欢&# 39;尝试比较所有数字,但只是一个懒惰的选择,然后你就会很好。
正如dfeuer所言,如果您创建Time
实例,还可以将<
直接与Ord
进行比较。与Eq
类似,可以自动导出
data Time = Time { ... }
deriving (Show, Eq, Ord)
但请注意:记录字段需要按照正确的顺序才能使词典顺序有意义(您不想要9:45 > 10:15
!)