【问题标题】:Scala 3 multiversal equality of type parametersScala 3 类型参数的多元相等性
【发布时间】:2022-12-11 08:49:58
【问题描述】:

在 Scala 3 中,使用 -language:strictEquality,此代码:

trait X[A]:
    def val1: A
    def val2: A
    def f() =
        if val1 == val2 then
            println("Same")

产生此错误:

Values of types A and A cannot be compared with == or !=

我寻找一些特征来告诉编​​译器 A 可以与自身进行比较,但找不到。我找到的解决方案是添加这一行:

given CanEqual[A, A] = CanEqual.derived

但是,我还有几个问题:

  1. 为什么不能比较同一类型的两个实例?有哪些 A 的实例,其中 val1 == val2 是不合法的?
  2. 是否有将 ==、!= 添加到类型的特征?
  3. 如果当A 是类型参数时编译器无法确定您可以将A 与A 进行比较,那么given CanEqual[A, A] = CanEqual.derived 是如何让它开心的? CanEqual.derived有什么神奇之处,为什么在使用==时不能默认应用?

【问题讨论】:

    标签: scala scala-3


    【解决方案1】:
    1. 这种比较并不是真的非法,它只是未定义。

    2. given 解决方案比 trait 更灵活,但如果您愿意,您可以只在您的类型上定义 ==。

    3. 您已明确告诉编译器您不希望它生成默认的 == 运算符。这就是strictEquality 的意思。

      strictEquality 背后的逻辑是存在不同种类的相等性,编译器不应该任意选择一种。对象可以通过引用或内容进行比较,但并不是在所有情况下都“正确”。

      如果没有strictEquality,编译器默认实现引用相等,这意味着两个值只有在引用同一个对象时才相同。 case class 通过检查每个字段是否相等来实现结构相等,因此如果所有字段的所有值都相同,则两个不同的实例“相等”。其他类可以通过仅比较字段的相关子集或其他标准来实现相等性。

      根据 the documentation 的说法,出于兼容性和迁移原因,选择加入严格相等。

    【讨论】:

    • “你不是在比较类型,你是在比较价值,这是相当不同的。” -- 是的,这就是我的意思,我澄清了问题。
    猜你喜欢
    • 2012-02-23
    • 2012-07-12
    • 1970-01-01
    • 2023-02-14
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    相关资源
    最近更新 更多