Reputation: 3185
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.
Upvotes: 3
Views: 112
Reputation: 139038
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.
Upvotes: 4