The following code gives an error.
class Base { }
class Sub extends Base { }
class Writer[-T] {
def write(t: T) { }
}
object AmbImplicits {
implicit object BaseWriter extends Writer[Base]
implicit object SubWriter extends Writer[Sub]
def foo[T](t: T)(implicit ev: Writer[T]) {
println(s"foo $t $ev")
}
def main(args: Array[String]) {
val base = new Base
val sub = new Sub
foo(base)
foo(sub)
}
}
The error:
/Workspace/AmbImplicits.scala:24: error: ambiguous implicit values:
both object SubWriter in object AmbImplicits of type AmbImplicits.SubWriter.type
and object BaseWriter in object AmbImplicits of type AmbImplicits.BaseWriter.type
match expected type Writer[Sub]
foo(sub)
^
In my real code it is not so simple to explicitly pass the implicit parameter. Is there way to tell it to always prefer SubWriter
over BaseWriter
, because the former is more specific? Without manually passing it like foo(sub)(SubWriter)
?
If you can't do what Shadowlands suggests due to Base and Sub being Java types, you can just reduce the priority of the BaseWriter
implicit by moving it up the inheritance chain:
trait LowPriorityImplicits { implicit object BaseWriter extends Writer[Base] }
object AmbImplicits extends LowPriorityImplicits {
implicit object SubWriter extends Writer[Sub]
def foo[T](t: T)(implicit ev: Writer[T]) {
println(s"foo $t $ev")
}
def main(args: Array[String]) {
val base = new Base
val sub = new Sub
foo(base)
foo(sub)
}
}