blob: b1b6c0380a509b0ead5d7f34a963de7c7753c866 (
plain) (
tree)
|
|
package strawman.equality
import annotation.implicitNotFound
object EqualityStrawman1 {
trait Eq[-T]
@implicitNotFound("cannot compare value of type ${T} with a value outside its equality class")
trait Impossible[T]
object Eq extends Eq[Any]
trait Base {
def === (other: Any): Boolean = this.equals(other)
def === [T <: CondEquals](other: T)(implicit ce: Impossible[T]): Boolean = ???
}
trait CondEquals extends Base {
def === [T >: this.type <: CondEquals](other: T)(implicit ce: Eq[T]): Boolean = this.equals(other)
def === [T](other: T)(implicit ce: Impossible[T]): Boolean = ???
}
trait Equals[-T] extends CondEquals
case class Str(str: String) extends CondEquals
case class Num(x: Int) extends Equals[Num]
case class Other(x: Int) extends Base
trait Option[+T] extends CondEquals
case class Some[+T](x: T) extends Option[T]
case object None extends Option[Nothing]
implicit def eqStr: Eq[Str] = Eq
//implicit def eqNum: Eq[Num] = Eq
implicit def eqOption[T: Eq]: Eq[Option[T]] = Eq
implicit def eqEq[T <: Equals[T]]: Eq[T] = Eq
def main(args: Array[String]): Unit = {
val x = Str("abc")
x === x
val n = Num(2)
val m = Num(3)
n === m
Other(1) === Other(2)
Some(x) === None
Some(x) === Some(Str(""))
val z: Option[Str] = Some(Str("abc"))
z === Some(x)
z === None
Some(x) === z
None === z
def ddistinct[T <: Base: Eq](xs: List[T]): List[T] = xs match {
case Nil => Nil
case x :: xs => x :: xs.filterNot(x === _)
}
ddistinct(List(z, z, z))
x === n // error
n === x // error
x === Other(1) // error
Other(2) === x // error
z === Some(n) // error
z === n // error
Some(n) === z // error
n === z // error
Other(1) === z // error
z === Other(1) // error
ddistinct(List(z, n)) // error
}
}
|