I have this fairly simple example where one function foo()
, which takes an implicit argument of type A
, tries to call another function bar()
, which takes an implicit argument of type B
. In the project where I ran into this question, B
contains a subset of the functionality of A
, so I would like to provide an implicit conversion from A
to B
to make cases like in this example seamless.
Implementing this using the implicit conversion B.implicitConversion()
works as expected. The following code is accepted by scalac
2.13.0:
trait A
trait B
object B {
// implicit class ImplicitClass(value: A) extends B
implicit def implicitConversion(implicit se: A) = ???
}
class Test {
def foo()(implicit a: A) = bar()
def bar()(implicit b: B) = ???
}
Oddly enough, implementing the conversion using the implicit class ImplicitClass
does not work (by removing the definition of implicitConversion()
and adding the definition of ImplicitClass
). The code is rejected by scalac
:
$ scalac 'Test.scala:12: error: could not find implicit value for parameter b: B
def foo()(implicit a: A) = bar()
^
one error found
I would have assumed that in such a situation implicit classes and implicit conversion are interchangeable. What am I missing here, why are the two ways of providing a conversion not equivalent?
ImplicitClass
is equivalent to
class ImplicitClass(value: A) extends B
implicit def ImplicitClass(value: A): ImplicitClass
You can see the difference: this implicit conversion takes value: A
as an explicit parameter, unlike your def implicitConversion
. And if you change to
def foo()(implicit a: A) = bar()(a)
you'll see it work.