Haskell 哈斯凯尔错误:“;没有因使用'==';

Haskell 哈斯凯尔错误:“;没有因使用'==';,haskell,Haskell,我是Haskell的新手,我不明白为什么我不能比较这两个变量。 我有这个功能: nextMinute :: Date -> Time -> DateTime nextMinute date time = if time == Time 23 59 then DateTime (tomorrow date) newDay else DateTime date (timeSucc time) 我

我是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)

您不必使用
==
,只需进行模式匹配即可:

nextMinute :: Date -> Time -> DateTime
nextMinute date (Time 23 59) = DateTime (tomorrow date) newDay
nextMinute date time         = DateTime date            (timeSucc time)

Eq
添加到您的
Time
类型中可能很好,但没有特别的需要,因为模式匹配有一个同样好的解决方案。

相等比较在Haskell中有点代码味道。如果你发现自己使用它,总是考虑是否应该更好地使用模式匹配,正如AM合金的答案。模式匹配往往更有效,而且即使在真正不可能相等的情况下(例如,在无限长列表上†)通常仍然有效

除此之外,在我看来,有些类型的情况下,你最好完全避免任何平等的假设。这包括表示某些连续物理量的所有类型,例如时间。从数学上讲,有两个这样的值。从更实际的角度来看,您的方法存在这样的风险:如果您以某种方式超出了准确值
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

†事实上,无限长列表上的相等问题与实数上的相等问题大致相同,如果您将它们描绘为无限长十进制展开式。当然,我们通常使用的数字类型实际上并不是无限精度的,但奇怪的是,假装这样通常会有帮助:实际上,浮点数会受到各种令人讨厌的不确定性问题的影响,但如果你只是简单地不尝试比较所有数字,而只是一个惰性的选择,那么你基本上就没事了



正如dfeuer所说,你也可以直接比较
Time
s和
Time
Where's from?对不起,时间和其他参数是在别处声明的,我也应该发布它们吗?你可能只需要在
Time
的定义中添加
派生(Eq…)
(我想你已经有了
派生(Show)
所以它是
派生(Show,Eq)
啊,天哪,谢谢你!!你已经帮了我这个问题了!:D时间声明如下:数据时间=时小时分钟派生(Show)必须是数据时间=时小时分钟派生(Show,Eq)是的,谢谢大家!
data Time = Time { ... }
 deriving (Show, Eq, Ord)