I would like the following code to compile, after making forgetBA implicit again.
trait ImplicitExample {
trait AA[T]
trait AB[T] extends AA[T]
trait BA[T] extends AA[T]
trait BB[T] extends AB[T] with BA[T]
object AA {
implicit def forgetAB[T: AB]: AA[T] = implicitly[AA[T]]
/*implicit*/ def forgetBA[T: BA]: AA[T] = implicitly[AA[T]]
}
object AB {
implicit def forgetBB[T: BB]: AB[T] = implicitly[AB[T]]
}
object BA {
implicit def forgetBB[T: BB]: BA[T] = implicitly[BA[T]]
}
object BB {
implicit object BBInt extends BB[Int]
}
val AAInt = implicitly[AA[Int]]
}
I understand that this will result in an ambiguous implicit resolution problem, so I'm looking for a way to indicate a preference for one implicit resolution over the other.
I've heard rumours that inserting intermediate traits in some way might help, but I can't seem to find an explanation.
The usual trick is to write something like this:
trait LowPriorityAAInstances {
implicit def forgetAB[T: AB]: AA[T] = implicitly[AA[T]]
}
object AA extends LowPriorityAAInstances {
implicit def forgetBA[T: BA]: AA[T] = implicitly[AA[T]]
}
This will give forgetBA priority when looking for an instance of AA for a T for which there's an instance of BA (while still compiling even if there's an instance of AB around).
The naming is entirely a matter of convention, but it's a good idea to use it to indicate that you're only breaking up the definition of AA in this way to accommodate the implicit search mechanism.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With