I have an opaque type FancyDouble
, which is implicitly converted from Double by using given Conversion[Double, FancyDouble] = FancyDouble(_)
in the companion object scope. After that, the construction val d: FancyDouble = 0.0
works, but when I try to do the comparison like if (d == 0.0)
, the compiler is complaining that I can't compare FanceDouble
and Double
(I am expecting that it should implicitly convert the 0.0
literal into FancyDouble, like in the previous case.
How can I enable the comparison with implicit conversions?
CodePudding user response:
Equality is essentially defined as (Any, Any) => Boolean
. Mostly because of Java legacy. That means that in fancyDouble == double
the expected type of expression double
is Any
and no implicit conversion will ever trigger.
However Scala 3 introduced the CanEqual
typeclass to make equality a bit safer. If you want to compare values of type A
and B
, an implicit instance of CanEqual[A, B]
needs to be in the implicit scope.
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
If you enable the strictEquality
flag, you even need a CanEqual[FancyDouble, FancyDouble]
in order to compare two FancyDouble
s.