3

次のコードでは、 の証拠がR[A]ありB、 のサブタイプであるため、のタイプを推測して証拠を使用するAことを期待します。しかし、scalac はそうすることを拒否します。fooARA

trait R[T]

case class A(i: Int)

object A {

  implicit object RA extends R[A]

}

class B(i: Int) extends A(i)

def foo[T](x : T)(implicit ev: R[T]) = 0

println(foo(new B(1))) // infers T as B and fails to find implicit R[B]

println(foo(new B(1) : A)) // Works, but undesirable

私はこれを試しました:

def foo[T, TT >: T](x : T)(implicit ev: R[TT]) = 0

しかし、それでもうまくいきません。

さて、私が定義すると:

def foo[T](x : T)(implicit ev: R[TT] forSome {type TT <: T}) = 0

推論は機能しますが、実際のコードでは TT を参照する必要があります。

編集: A の証拠を A コンパニオン オブジェクトに移動したので、この解決策はもう機能しないようです。現実的な設定では、証拠は常にコンパニオン オブジェクトにあり、暗黙の検索でそれを見つける必要があります。

別の解決策は、証拠を反変にすることですが、これは推論Nothingやその他の問題など、多くの問題を引き起こします (私の実際のコードは、この単純化された例よりも複雑です)。

どうすればこれを正しく機能させることができますか?

4

1 に答える 1

0

あなたが使用することができます

def foo[T, TT](x : T)(implicit ev: R[_ >: T] with R[TT]) = 0

TT を参照してください。

編集:次のコードは、反変性を使用してコンパニオン オブジェクト内の証拠を見つけます。また、TT が T のスーパータイプであることもエンコードします。 は推論しませんNothingが、反変性に関する他の問題について言及しました。それらを回避することは可能ですか?

trait R[-T]

case class A(i: Int)

object A {

  implicit object RA extends R[A]

}

class B(i: Int) extends A(i)

def foo[T, TT](x : T)(implicit ev1: R[T] with R[TT], ev2: T <:< TT) = 0

println(foo(new B(1))) // infers TT as A
于 2015-02-21T07:09:54.553 に答える