You can roll your own:
trait NoInstance[T[_], A]
object NoInstance extends LowPriorityNoInstance {
implicit def hasInstance0[T[_], A](implicit inst: T[A]): NoInstance[T, A] = ???
implicit def hasInstance1[T[_], A](implicit inst: T[A]): NoInstance[T, A] = ???
}
class LowPriorityNoInstance {
implicit def noInstance[T[_], A]: NoInstance[T, A] = new NoInstance[T, A] {}
}
And then:
scala> implicitly[NoInstance[Ordering, List[Int]]]
res4: NoInstance[Ordering,List[Int]] = LowPriorityNoInstance$$anon$1@5e1fc2aa
scala> implicitly[NoInstance[Ordering, Int]]
<console>:14: error: ambiguous implicit values:
both method hasInstance0 in object NoInstance of type [T[_], A](implicit inst: T[A])NoInstance[T,A]
and method hasInstance1 in object NoInstance of type [T[_], A](implicit inst: T[A])NoInstance[T,A]
match expected type NoInstance[Ordering,Int]
implicitly[NoInstance[Ordering, Int]]
^
In many cases you can avoid this kind of thing with the null
default implicit parameter trick, though:
def f[T](x: T)(implicit stc: SomeTypeclass[T] = null): Unit = Option(stc) match {
case Some(instance) => // do something in the case where we have an instance
case None => // do something in the case where we don't have an instance
}
This feels like a hack, but it works and people use it all the time.