Question: Why defining a wrapping method over another method with an implicit argument doesn't work?

Question

Why defining a wrapping method over another method with an implicit argument doesn't work?

Answers 1
Added at 2017-01-01 18:01
Tags
Question

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?

Answers
nr: #1 dodano: 2017-01-01 19:01

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.

Source Show
◀ Wstecz