I have the following piece of Scala with ambigiuous implicits, which I would have thought should work, due to lower priority given to inherited implicits. But it does not - it fails with an ambiguous implicit values
-error. Can someone explain to me why priorities does not work here?
trait Printer[-T] {
def prettify(instance:T): String
}
trait LowPriorityPrinter {
implicit val anyPrinter:Printer[Any] = new Printer[Any]{ def prettify(instance:Any) = instance.toString() }
}
object Printer extends LowPriorityPrinter {
implicit val intPrinter = new Printer[Int]{ def prettify(instance:Int) = instance.toString() }
}
object MyApp extends App {
def prettyprint[T](i:T)(implicit p:Printer[T]) = println(p.prettify(i))
prettyprint(234)
}
The issue is simple, but nasty. The LowPriorityPrinter
catch all instance of your type class needs to be generic, not for Any
:
object Printer {
implicit val intPrinter: Printer[Int] =
new Printer[T]{ def prettify(x: T) = x.toString() + " (int") }
implicit def anyPrinter[T]: Printer[T] =
new Printer[T]{ def prettify(x: T) = x.toString() + " (general) }
}
Basically, the literal 234
is just as much an Int
as it as an Any
and neither of those types is more specific than the other (so the priority trick is useless).