Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing all implementations of a trait to override equals

Tags:

scala

I have a trait for which I know that reference equality is never the correct implementation of equals. Implementations of the trait can be written by many users, and practice shows that sometimes they fail to override equals. Is there a way to require it?

In practice implementations are usually case classes, which override equals automatically, and we can approach requiring that by having Product as the self-type of the trait, however, I'd like to see a solution which allows non-case classes overriding equals as well (EDIT: Using scala.Equals as the self-type is a closer approximation to what I want, since it's still implemented automatically by case classes, but can be usefully implemented by non-case classes and isn't a large burden on people writing implementations).

One more approach I thought of while writing this question is to override equals in the trait to call an abstract method, but unfortunately, this doesn't work for case class implementations.

like image 541
Alexey Romanov Avatar asked Apr 19 '15 14:04

Alexey Romanov


1 Answers

Why not use typeclass contract instead of pure trait? We have one already in scalaz, and it's easy to glue it with Equals trait:

import scalaz._

case class X(a:Int,b:Int)

class Y(a:Int,b:Int)

implicit def provideDefaultEqual[T <: Equals]:Equal[T] = new Equal[T] {
  def equal(a1: T, a2: T) = a1 == a2
}

implicitly[Equal[X]]

implicitly[Equal[Y]] //compile error

If you need to wire this with your trait, there is your own nice solution

like image 83
Odomontois Avatar answered Nov 15 '22 19:11

Odomontois