は ではないためFoo[Bleh]
、使用できません。として使用するには、反変を onにする必要があります。Foo[Blah]
Foo[Bleh]
Foo[Blah]
Foo
A
Foo[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 番目のパラメーター グループが型パラメーターに影響を与えることはできません。