Type constraint for type inequality in scala
scala, type-systems
Solution
shapeless defines the type operator `A <:!< B` (meaning `A` is not a subtype of `B`) using the same implicit ambiguity trick that's used for strict type inequality,
trait <:!<[A, B]
implicit def nsub[A, B] : A <:!< B = new <:!<[A, B] {}
implicit def nsubAmbig1[A, B >: A] : A <:!< B = sys.error("Unexpected call")
implicit def nsubAmbig2[A, B >: A] : A <:!< B = sys.error("Unexpected call")
Sample REPL session,
scala> import shapeless.TypeOperators._
import shapeless.TypeOperators._
scala> implicitly[Int <:!< String]
res0: shapeless.TypeOperators.<:!<[Int,String] =
shapeless.TypeOperators$$anon$2@200fde5c
scala> implicitly[Int <:!< Int]
<console>:11: error: ambiguous implicit values:
both method nsubAmbig1 in object TypeOperators of type
[A, B >: A]=> shapeless.TypeOperators.<:!<[A,B]
and method nsubAmbig2 in object TypeOperators of type
[A, B >: A]=> shapeless.TypeOperators.<:!<[A,B]
match expected type shapeless.TypeOperators.<:!<[Int,Int]
implicitly[Int <:!< Int]
^
scala> class Foo ; class Bar extends Foo
defined class Foo
defined class Bar
scala> implicitly[Foo <:!< Bar]
res2: shapeless.TypeOperators.<:!<[Foo,Bar] =
shapeless.TypeOperators$$anon$2@871f548
scala> implicitly[Bar <:!< Foo]
<console>:13: error: ambiguous implicit values:
both method nsubAmbig1 in object TypeOperators of type
[A, B >: A]=> shapeless.TypeOperators.<:!<[A,B]
and method nsubAmbig2 in object TypeOperators of type
[A, B >: A]=> shapeless.TypeOperators.<:!<[A,B]
match expected type shapeless.TypeOperators.<:!<[Bar,Foo]
implicitly[Bar <:!< Foo]
^
Problem
Possible Duplicate: Enforce type difference Since there is a generalized type constraint enforcing equality in scala `=:=`, is there one that enforces "not equals" for types? Basically `!=` but for types? Edit Comment below points to an existing Q&A and the answer seems to be that (1) no, it's not in the standard library (2) yes, it's possible to define one. So I'll modify my question because of a thought that occurred to me after I saw the answer. Given the existing solution: ``` 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) ``` If `A <: B` or `A >: B`, will it still be the case that `A =!= B`? If not, is it possible to modify the solution such that if `A =!= B` then it is not the case that `A <: B` or `A >: B`?