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 ?