2

y を x に追加できるものに変換しようとしています。ここで、x はある種のシーケンスです。

scala> def foo[U <: Seq[T], T](x: U, y: T): U = x :+ y
<console>:7: error: type mismatch;
 found   : Seq[T]
 required: U
       def foo[U <: Seq[T], T](x: U, y: T): U = x :+ y
                                                  ^

次の解決策があります。

def foo[T]( x : Seq[T], y:T) = x :+ y
def foo[T]( x : Seq[T], y:T) : Seq[T] = x :+ y
def foo[U <: Seq[T], T](x: U, y: T): U = (x :+ y).asInstanceOf[U]

しかし、私の疑問は、元のものが機能しなかった理由です。:+スーパークラスで定義された演算子(この場合)を適用すると、スーパークラスが返されるように見えますか?つまり、がU返されるので、エラーが発生します。VectorfooSeqrequired "U" but found "Seq[T]"

この動作が見られる理由を教えてもらえますか?

4

2 に答える 2

3

型の問題に遭遇したとき、私は通常、「コンパイルを通過するとどうなるか」というロジックを採用して、不合理な部分を見つけます。

あなたの場合、元のものは大丈夫だと仮定します。

 def foo[U <: Seq[T], T](x: U, y: T): U = x :+ y

cause Seq[T] は T 上で共変であるため、次のケースが成り立ちます。

 for type A, T, if A <: T, List[A] <: Seq[T]

次に、次の操作を実行できます。

 class Parent 
 class Child extends Parent

 // List(new Child) :+ (new Parent) => List[Parent]
val result = foo(List(new Child), new Parent)

U は実際には foo メソッドの List[Child] ですが、List がその要素の型とは異なる型で動作する場合、共通の親を見つけようとします。この場合、結果は List[Parent] で型付けされますが、必要な型はリスト[子]です。明らかに、List[Parent] は List[Child] のサブタイプではありません。

したがって、最終的なタイプは昇格されますが、必要なタイプは昇格されたタイプのサブタイプです。Scala SeqLike の定義を見れば、これはより明確になるかもしれません。

trait SeqLike[+A, +Repr] extends ... {
    def :+[B >: A, That](elem: B)(...): That = {
       ...
    }
}
于 2015-07-31T07:38:10.690 に答える
2

この例を単純化しましょう

  class T
  class B extends T

  def bar[U <: T](x: T): U = {
    new B
  }

これはコンパイルされません。

bar(new T)

タイプ T を返す必要がありますが、タイプ B を返そうとしています。B は T のサブタイプですが、正確に U を返す必要がありますが、T の場合は単なるサブタイプではありません。

あなたはあなたの問題を解決することができます

def foo[U <: Seq[T], T](x: U, y: T): Seq[T] = x :+ y

また

def foo[B >: Seq[T], U <: Seq[T], T](x: U, y: T): B = y +: x
于 2015-07-31T07:04:15.620 に答える