は ではないためFoo[Bleh]、使用できません。として使用するには、反変を onにする必要があります。Foo[Blah]Foo[Bleh]Foo[Blah]FooAFoo[Bleh]Foo[Blah]
trait Foo[-A] {
def bar(a: A) = println(a) // to make Foo contravariant
}
これはうまくいきます:
scala> foo1(Blah())
res0: Blah = Blah()
元のコードには、質問に対する回答が含まれています。Foo[Bleh]オリジナルを次のように使用できると仮定しましょうFoo[Blah]:
def foo1[A:Foo](): A = implicitly[Foo[A]].bar
val b: Blah = foo1[Blah]()
ここFoo[Bleh]で が使用されている場合Bleh、 の結果として得られbarますが、期待していてBlah、 でBlehはありませんBlah。
幸いなことに、コンパイラはオリジナルFoo[Bleh]をFoo[Blah]次のように使用することを許可しません。
scala> trait Foo[-A] {
| def bar: A
| }
<console>:8: error: contravariant type A occurs in covariant position in type => A of method bar
def bar: A
^
型推論
これはうまくいきます:
foo1[Bleh](Blah())
ただし、コンパイラはAここで型パラメーターを として推論しませんBleh。「なぜ」を理解するには、次のA:Foo意味を理解する必要があります。
def foo1[A:Foo](a:A) = a // syntax sugar
def foo1[A](a:A)(implicit ev: Foo[A]) = a // same method
A:Foo追加の暗黙的なパラメーターの構文シュガーです。
2 つのパラメーター グループがある場合、コンパイラは最初のグループの型を推測し、その型が既知であると見なします。そのため、最初のパラメーター グループ(a:A)の型Blahが既知であり、2 番目のパラメーター グループが型パラメーターに影響を与えることはできません。