Scala 3 隐式转换:比较值和文字

Scala 3 implicit conversions: compare value and literal

我有一个不透明类型 FancyDouble,它是通过在伴随对象范围内使用 given Conversion[Double, FancyDouble] = FancyDouble(_) 从 Double 隐式转换而来的。在那之后,构造 val d: FancyDouble = 0.0 起作用了,但是当我尝试像 if (d == 0.0) 那样进行比较时,编译器抱怨我无法比较 FanceDoubleDouble(我我期待它应该隐式地将 0.0 文字转换为 FancyDouble,就像在前面的例子中一样。

如何启用隐式转换比较?

平等本质上定义为(Any, Any) => Boolean。主要是因为 Java 遗产。这意味着在 fancyDouble == double 中,预期的表达式类型 doubleAny 并且不会触发任何隐式转换。

但是 Scala 3 introduced CanEqual 类型类使平等更安全一些。如果要比较类型 AB 的值,CanEqual[A, B] 的隐式实例需要在隐式范围内。

object fancy {
  opaque type FancyDouble = Double
  def make(d: Double): FancyDouble = d

  given CanEqual[FancyDouble, Double] = CanEqual.derived
  given CanEqual[Double, FancyDouble] = CanEqual.derived
}

val a = 4.2
val b = fancy.make(4.2)

assert(a == b) // ok
assert(b == a) // ok

如果启用 strictEquality 标志,您甚至需要一个 CanEqual[FancyDouble, FancyDouble] 来比较两个 FancyDouble