Reputation: 1241
writing this fails type check:
val list = List(1,3,5,2,4)
list sortBy (i => -i) //this is ok
def wrappedSort[A,B](a: List[A])(by: A => B): List[A] = {
a sortBy by
} // this fails type check
wrappedSort(list)(i => -i) //So this won't work either
We know the compile error is: No implicit Ordering defined for B.
To make it work I had to have the Wrapper method have the same implicit argument as the wrapped method's which is:
import math.Ordering
def wrappedSort[A,B](a: List[A])(by: A => B)(implicit ord: Ordering[B]): List[A] = {
a sortBy by
}
But this is quite annoying. when working to abstract or extend over some library code, I come across some complicated context bounds that I must re-implement manually. is there a workaround for this in which I don't have to specify the implicit argument in my own abstracions?
Upvotes: 0
Views: 53
Reputation: 35980
In this case, PreDef
(which is in scope everywhere unless you specifically disable it in the compiler) there is an instance of Ordering[Int]
available. Hence, the compiler doesn't fail because it's in scope and it knows the exact implicit it has to search to find. When you provide an abstract B
with that function signature, you effectively tell the compiler that B
will not be supplied with an Ordering
for all B
(which is effectively every single type in the known universe) and the requirement that B
have an Ordering
as dictated by the sortBy
function on List
is failed immediately.
There really isn't a way to avoid this nor should you want to avoid it at all. It's by design and a safety feature of the compiler.
Upvotes: 3