次の 2 つの特性があるとします。
trait Foo[A] { def howMany(xs: List[A]) = xs.size }
trait Bar
そして、2 番目から 1 番目への暗黙的な変換:
implicit def bar2foo[A](bar: Bar) = new Foo[A] {}
Bar
と整数のリストを作成します。
val bar = new Bar {}
val stuff = List(1, 2, 3)
今、私は次のように動作することを期待しています:
bar howMany stuff
しかし、そうではありません:
scala> bar howMany stuff
<console>:13: error: type mismatch;
found : List[Int]
required: List[A]
bar howMany stuff
^
そこで、specに移動します。これには次のように書かれています (太字の強調は私のものです)。
ビューは 3 つの状況で適用されます。
【ここは関係ない】
タイプTのeを持つ選択emで、セレクターmがTのメンバーを示さない場合。この場合、eに適用可能で、その結果にmという名前のメンバーが含まれるビューvが検索されます。検索は、暗黙のパラメーターの場合と同様に進行します。ここで、暗黙のスコープはTのスコープです。そのようなビューが見つかった場合、選択emはv(e).mに変換されます。
タイプTのeを持つ選択em(args)で、セレクターmがTの一部のメンバーを示しているが、これらのメンバーのいずれも引数argsに適用できない場合。この場合、eに適用可能なビューvが検索され、その結果にはargs に適用可能なメソッドmが含まれます。検索は、暗黙のパラメーターの場合と同様に進行します。ここで、暗黙のスコープはTのスコープです。そのようなビューが見つかった場合、選択emはv(e).m(args)に変換され ます。
そこで、私たちは次のことを試みます。
trait Foo[A] { def howMany(xs: List[A]) = xs.size }
trait Bar { def howMany = throw new Exception("I don't do anything!") }
implicit def bar2foo[A](bar: Bar) = new Foo[A] {}
val bar = new Bar {}
val stuff = List(1, 2, 3)
ただし、(少なくとも 2.9.2 と 2.10.0-RC2 の両方で):
scala> bar howMany stuff
res0: Int = 3
これは、この問題の回避策の例のように、いくつかの非常に奇妙な動作につながります。
3 つの (密接に関連する) 質問があります。
- 上記の元のケースでビューを正しく適用する簡単な方法 (つまり、適切な名前で偽のメソッドを追加する必要がない方法) はありますか?
- 誰かがこの動作を説明する仕様の読みを提供できますか?
- これが意図された動作であると仮定すると、まったく意味がありますか?
また、この問題に関する以前の議論へのリンクもあれば幸いです。Google とのやり取りはあまりうまくいきませんでした。