Enforce type difference

scala, types

Solution

Riffing off of Jean-Philippe's ideas, this works:

sealed class =!=[A,B]

trait LowerPriorityImplicits {
  implicit def equal[A]: =!=[A, A] = sys.error("should not be called")
}
object =!= extends LowerPriorityImplicits {
  implicit def nequal[A,B](implicit same: A =:= B = null): =!=[A,B] = 
    if (same != null) sys.error("should not be called explicitly with same type")
    else new =!=[A,B]
}     

case class Foo[A,B](a: A, b: B)(implicit e: A =!= B)

Then:

// compiles:
Foo(1f, 1.0)
Foo("", 1.0)
Foo("", 1)
Foo("Fish", Some("Fish"))

// doesn't compile
// Foo(1f, 1f)
// Foo("", "")

I'd probably simplify this as follows, since the checks for "cheating" can always be circumvented anyway (e.g. `Foo(1, 1)(null)` or `=!=.nequal(null)`):

sealed class =!=[A,B]

trait LowerPriorityImplicits {
  /** do not call explicitly! */
  implicit def equal[A]: =!=[A, A] = sys.error("should not be called")
}
object =!= extends LowerPriorityImplicits {
  /** do not call explicitly! */
  implicit def nequal[A,B]: =!=[A,B] = new =!=[A,B]
}

Problem

In Scala I can enforce type equality at compile time. For example: ``` case class Foo[A,B]( a: A, b: B )( implicit ev: A =:= B ) scala> Foo( 1, 2 ) res3: Foo[Int,Int] = Foo(1,2) scala> Foo( 1, "2" ) <console>:10: error: Cannot prove that Int =:= java.lang.String. ``` Is there a way to enforce that type A and type B should be different ?

Original source