Knows Not Much Knows Not Much - 2 months ago 8
Scala Question

Scala Implicits compilation error

I wrote this code

case class Foo(x: Int)
case class Bar(y: Int)
object Foo {
implicit def toBar(f: Foo) : Bar = { Bar(f.x) }
implicit def toBarList(fl: List[Foo]) : List[Bar] = {fl.map{x: Bar => x}}


The toBarList function doesn't compile.

<console>:17: error: type mismatch;
found : Bar => Bar
required: Foo => ?
implicit def toBarList(fl : List[Foo]) : List[Bar] = { fl.map{x : Bar => x}}


However shouldn't the implicits system kick in here? meaning that compiler should detect that there is an error that the function expects a Bar but I am passing a Foo. Now there is already a implicit function in scope which converts Foo to a Bar, so that should be used and things should work.

So why did this not compile?

Answer

map is an ordinary method that takes a function argument, and map on a List[Foo] requires a function from Foo. You've provided an function from Bar—specifically Bar => Bar—but having an implicit conversion from Foo to Bar doesn't mean you have one from Bar => Bar to Foo => Bar (which is what the method needs).

If you want this to work you'll either need to provide a function from Foo and then apply the conversion (either explicitly or implicitly), or you'll need to provide an implicit conversion from Bar => Bar to Foo => Bar (similar to the one you're trying to provide from List[Foo] to List[Bar], but with the conversion happening in the other direction, since Function1 is contravariant in its first argument while List is covariant).

(This is all a very bad idea, though.)