使用泛型隐式参数的隐式转换

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

}

这是因为理论上存在任何限制吗?还是这是实现的一个局限性?
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,而值得关注的候选者是toT: [T](foo: this.Foo)(implicit g: Int => T)T”。接下来是输出,表明Scala尝试实例化T,但第81行最终指出:

inferMethodInstance, still undetermined: List(type T)

我的理解是,Scala在某些情况下无法实例化TZip,因此最终被舍弃。


话虽如此,我认为你的代码在理论上没有问题,我认为这只是编译器的缺陷。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接