【问题标题】:What happens if we derive Ord but not Eq while making a data type?如果我们在创建数据类型时导出 Ord 而不是 Eq 会发生什么?
【发布时间】:2023-04-07 21:07:01
【问题描述】:

我知道在 haskell 中,如果我们创建一个派生 Ord 的数据类型,它也应该派生 Eq,但是为什么我们必须在定义中明确地写出它们呢?

【问题讨论】:

  • 有时您可以提供比派生的实例快得多的Eq 实例。 interned 字符串(和其他内部结构)背后的想法是您可以在 O(1) 时间内比较它们是否相等。我可以看到类似的情况,但略有不同,您可能需要来自 deriving 的标准 Ord 实例,但需要特殊的 Eq 实例。

标签: haskell


【解决方案1】:

可以合理地推导出Ord,但手动实例化Eq

data Foo = Foo deriving Ord
instance Eq Foo where
    _ == _ = True

我想不出一个有用的地方,但没有理由阻止它。

【讨论】:

  • 还有更灵活的定义:data Foo = ... deriving (Ord); instance Eq Foo where x == y = compare x y == EQ。然后 GHC 会有效地自动生成这两个实例。
  • (当然,deriving (Eq, Ord) 或多或少已经这样做了,所以这可能不是超级有用。)
【解决方案2】:

您必须编写Eq 的原因与您必须在为Ord 编写实例之前(或至少在编译它之前)编写实例之前必须为Eq 编写实例相同。可以推导出一个,但该属性不适用于所有类型类上下文,因此您需要明确。

编译器可以很容易地知道派生Eq(这可能是相当无害的),但是如果没有明确要求它就拥有一个类型类的实例可能会引起一些意外。如果它以某种方式发生在更复杂的类型类上,这可能会非常令人困惑。

【讨论】:

  • 更大的问题是有时超类可以从几个子类中的任何一个派生出来。在这种情况下,它应该选择哪一个?例如,Functor 可以派生自 ApplicativeTraversableComonad
  • 这些都不能在数据声明中自动派生?
  • @Tesseract、TraversableFunctor 都可以使用合适的扩展名。当然这意味着 dfeuer 的模棱两可在实践中不可能发生,但这似乎更像是一个巧合,原则上这是一个值得思考的问题。
猜你喜欢
  • 2014-11-27
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 2018-08-04
相关资源
最近更新 更多