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 コンパイラの内部構造に詳しくありませんが、次の 2 つの出力スニペットは問題を示唆している可能性があります。最初のものは(要旨の51ff行目)です

[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 がどういうわけか でインスタンス化に失敗したTためZip、最終的に候補が破棄されたということです。


とはいえ、あなたのコードに理論的な問題は見られず、コンパイラの欠点に過ぎないと思います。

于 2012-11-01T13:30:13.500 に答える