【问题标题】:Can I use == and /= without using Eq?我可以在不使用 Eq 的情况下使用 == 和 /= 吗?
【发布时间】:2018-07-31 14:17:12
【问题描述】:

所以我写了这个程序,一切正常;) 我想改进它。我还可以使用 /= 编译两个不同的时间集并获得 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)

【问题讨论】:

  • 我很惊讶这行得通,因为datatype 需要以 upercase 开头。
  • 此外,我还不清楚问题所在。 “使用/= 的两个不同的时间集是什么意思?您可以定义different :: Time -> Time -> Bool,或使其成为Eq 的实例。
  • 我不想使用 Eq。是的,我可以定义“不同”,但我的问题是是否可以在一个函数中结合不同和相同。
  • “在一个函数中组合不同的和相同的”我不明白你的意思。我假设different a b 的结果与same a b 的结果不同,对吧?如果是这样,那么它们一定是两个不同的函数。
  • @BroniaBerlin:是的,添加一个额外的参数来指定你想要“相同”还是“不同”的风格。但标准方法是让Time 成为Eq 的实例,这样就可以重用(==) 用于各种对象。此外,突然之间,您可以使用像nub 这样的函数,其条件是它们num 的元素是Eq 类型。

标签: haskell algebraic-data-types


【解决方案1】:

回答标题中的问题:

我可以在不使用Eq 的情况下使用==/= 吗?

您可以 - 从技术上讲 - 在前奏中显式隐藏 Eq 类型类,然后自己定义 (==)(/=) 函数,但这不是一个好主意,因为这意味着你不能用(==)比较两个整数。

您可能想要将Time 设为Eq 类型类的实例,这样您就可以从现在开始编写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 将编写(==) 版本。当然你也可以同时实现。

使类型成为类型类的成员实际上很有用。以nub :: Eq a => [a] -> [a] 函数为例。它要求 a 类型是 Eq 类型类的成员,并执行某种“唯一性”过滤器:您为其提供一个元素列表,它返回一个 non-equal 的列表em> 元素。现在无需为您的Time 类型定义nub 函数,通过使Time 成为Eq 类型类的实例,您可以在Times 的列表中使用nub

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

【讨论】:

  • 谢谢!这很有帮助。你能告诉我如何在我的 ghci 中编译它吗?
  • @BroniaBerlin:你可以写在:{:}行之间来实现一个多行项目:stackoverflow.com/questions/8443035/multi-line-commands-in-ghci
  • 我以前从未使用过 Eq,所以我现在有点迷茫,所以如果我想比较两个时间集,我会写什么?
  • @BroniaBerlin: 如果你写Localtime 13 20 == Localtime 14 20,它就是False
  • 你做出了最好的回答,我一直很喜欢阅读你的帖子。恭喜。 +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-22
  • 1970-01-01
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 2012-03-28
相关资源
最近更新 更多