Knu*_*daa 6 scala implicit-conversion
我似乎将隐式转换与通用隐式参数结合起来不起作用,如下面的示例2b所示:
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
}
Run Code Online (Sandbox Code Playgroud)
有没有理论上的理由说明为什么这不起作用,或者它是否是实施的限制?
无论如何,如果您运行以下代码的简化版本
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
Run Code Online (Sandbox Code Playgroud)
使用-Yinfer-debug,您将获得大量有关幕后发生情况的调试信息(Scala 2.9.2)。我不熟悉 Scala 编译器的内部结构,但以下两个输出片段可能暗示了该问题。第一个是(要点的第 51 行)
[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
}
Run Code Online (Sandbox Code Playgroud)
我将其解释为“我们正在寻找一个隐式的this.Foo => this.Zip,并且值得关注的候选者是toT: [T](foo: this.Foo)(implicit g: Int => T)T。这个片段后面的输出表明 Scala 然后尝试实例化T,但第 81 行最后说
inferMethodInstance, still undetermined: List(type T)
Run Code Online (Sandbox Code Playgroud)
我的解释是,Scala 不知何故无法实例化T,Zip这就是候选者最终被丢弃的原因。
也就是说,我没有看到您的代码存在理论上的问题,并且我认为这只是编译器的缺点。