Reputation: 15742
I seems that combining implicit conversions with generic implicit parameters does not work, as in example 2b below:
object Test {
case class Foo(i: Int)
case class Bar(i: Int)
case class Zip(i: Int)
object Foo {
// 1)
implicit def toBar(foo: Foo)(implicit g: Int => Bar): Bar = g(foo.i)
// 2)
implicit def toT[T](foo: Foo)(implicit g: Int => T): T = g(foo.i)
}
// 1)
implicit val b = (i: Int) => Bar(i)
val bar: Bar = Foo(3)
// 2a)
implicit val z = (i: Int) => Zip(i)
val zip: Zip = Foo.toT(Foo(3))
// 2b)
val zip2: Zip = Foo(3) // <- compiler error, implicit conversion not applied
}
Is there any theoretical reason why this doesn't work, or is it a limitation of the implementation?
Upvotes: 6
Views: 292
Reputation: 12852
For what it's worth, if you run the following reduced version of your code
case class Foo(i: Int)
case class Zip(i: Int)
implicit def toT[T](foo: Foo)(implicit g: Int => T): T = g(foo.i)
implicit val z = (i: Int) => Zip(i)
val zip2: Zip = Foo(3) // <- compiler error, implicit conversion not applied
with -Yinfer-debug
, you'll get lots of debug information (Scala 2.9.2) about what is going on behind the scenes. I am not familiar with Scala compiler internals, but the following two output snippets might hint at the problem. The first one is (line 51ff of the gist)
[inferImplicit view] pt = this.Foo => this.Zip
Implicit search in Context(Main.$anon.zip2@ValDef scope=1100551785) {
search this.Foo => this.Zip
target $anon.this.Foo.apply(3)
isView true
eligible toT: [T](foo: this.Foo)(implicit g: Int => T)T
}
and I interpret it as "we are looking for an implicit this.Foo => this.Zip
and a candidate worth looking at is toT: [T](foo: this.Foo)(implicit g: Int => T)T
.
This snippet is followed by output that suggests that Scala then tries to instantiate T
, but line 81 finally says
inferMethodInstance, still undetermined: List(type T)
My interpretation is, that Scala somehow fails to instantiate T
with Zip
, which is why the candidate is finally discarded.
That said, I don't see a theoretical problem with your code, and I assume that it is only a shortcoming of the compiler.
Upvotes: 2