6

我似乎将隐式转换与通用隐式参数结合起来不起作用,如下面的示例 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

}

是否有任何理论上的原因导致这不起作用,或者它是实施的限制?

4

1 回答 1

2

对于它的价值,如果您运行以下代码的简化版本

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

使用-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
}

我将其解释为“我们正在寻找一个隐含this.Foo => this.Zip且值得一看的候选者 is toT: [T](foo: this.Foo)(implicit g: Int => T)T。这个片段后面是输出,表明 Scala 然后尝试实例化T,但第 81 行最后说

inferMethodInstance, still undetermined: List(type T)

我的解释是,Scala 以某种方式无法用 实例化TZip这就是最终放弃候选人的原因。


也就是说,我认为您的代码没有理论上的问题,我认为这只是编译器的一个缺点。

于 2012-11-01T13:30:13.500 回答