Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala 3 implicit conversions: compare value and literal

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?

like image 538
Alexander Temerev Avatar asked Nov 01 '21 13:11

Alexander Temerev


1 Answers

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 FancyDoubles.

like image 165
Jasper-M Avatar answered Nov 15 '22 05:11

Jasper-M