是否可以不使用Eq而使用==和/ =?

时间:2018-07-31 14:17:13

标签: haskell algebraic-data-types

所以我写了这个程序,一切正常;) 我想改善它。我还可以使用/ =编译两个不同的时间集,并得到True。 我有点困惑。

data Time = Localtime {hour, minute :: Int}
              | Globaltime {hour, minute, difference :: Int}
              | LocaltimeAM {hour, minute :: Int, am :: Bool} 
             deriving Show

same :: Time -> Time -> Bool
same u1 u2 = (h u1) == (h u2)
   where
      h :: Time -> (Int, Int) -- (Int, Int) = (hour, minute)
      h (Localtime h m) = (h, m)
      h (Globaltime h m d) = ((h+d+24) `mod` 24, m) 
      h (LocaltimeAM h m am) = (h + (if am then 0 else 12), m)

1 个答案:

答案 0 :(得分:15)

要回答标题中的问题:

  

我可以不使用==来使用/=Eq吗?

从技术上讲,您可以在前言中显式隐藏Eq类型类,然后自己定义(==)(/=)函数,但这将是一个坏主意,因为它意味着您将无法再将两个整数与(==)进行比较。

您可能想要使Time成为Eq类型类的 instance ,这样您就可以从现在开始编写time1 == time2。我们可以将其设置为以下实例:

h :: Time -> (Int, Int) -- (Int, Int) = (hour, minute)
h (Localtime h m) = (h, m)
h (Globaltime h m d) = ((h+d+24) `mod` 24, m) 
h (LocaltimeAM h m am) = (h + (if am then 0 else 12), m)

instance Eq Time where
    t1 == t2 = (h t1) == (h t2)

Haskell将自动为我们编写(/=)函数(与(==)相反),或者您可以决定编写(/=)版本,然后Haskell将编写{{ 1}}版本。当然,您也可以同时实现两者。

使类型成为类型类的成员实际上可能是有用的。以nub :: Eq a => [a] -> [a]函数为例。它要求类型(==)a类型类的成员,并执行某种“唯一性”过滤器:您向它提供一个元素列表,并返回一个 non列表。 -等于元素。现在,无需进行任何操作即可为您的Eq类型定义nub函数,通过将Time作为Time类型类的实例,您可以使用Eq nub的列表。

当然,您不能简单地将一个类型设为所有可能的类型类的实例。仅当可以检查两个项目是否相同时,才应将类型作为Time类型类的实例(因此,当两个项目相等时,应该有一个“合理的”想法)。此外,大多数这些类型类都带有“ 合约”:例如,等式关系(如Eq所定义的)应该是自反对称 transitive