5

通常、特定の型に一致するシーケンスのすべての要素を収集すると、結果のコレクションには、元のコレクションの型と選択された型の両方が含まれます。

trait Foo
trait Bar

trait Baz {
  // Works
  def def1(foo: Seq[Foo]): Seq[Foo with Bar] = 
    foo collect {case foobar: Bar => foobar}
}

これは、入力型がバインドされたメンバー型によってパラメーター化され、戻りたいのはバインドされた型 (メンバー型ではない) によってパラメーター化されたシーケンスのみである場合でも機能します。

trait Baz {
  type memberType <: Foo

  // Works
  def2(foo: Seq[memberType]): Seq[Foo with Bar] =
    foo collect {case foobar: Bar => foobar}
}

ただし、メンバー型によってパラメーター化されたシーケンスを実際に戻したい場合、これは失敗します。

trait Baz {
  type memberType <: Foo

  // Fails
  def def3(foo: Seq[memberType]): Seq[memberType with Bar] =
    foo collect {case foobar: Bar => foobar}
}

エラーメッセージ:

error: type mismatch;
 found   : Seq[this.Foo with this.Bar]
 required: Seq[Baz.this.memberType with this.Bar]
    foo collect {case foobar: Bar => foobar}

機能を回復するために、collect呼び出しにメンバー型を含めることができますが、署名のためにすべての要素がその型に一致する必要があることを考えると、それは冗長に思えます。

trait Baz {
  type memberType <: Foo

  // Works
  def def4(foo: Seq[memberType]): Seq[memberType with Bar] =
    foo collect {case foobar: memberType with Bar => foobar}
}

collectメンバー型のシーケンスを定義して、編集時にメンバー型を記憶する方法はありますか?

4

1 に答える 1

1

これは答えではありませんが、いくつかの観察です。これは機能します:

trait Baz[A <: Foo] {
  def def3(foo: Seq[A]): Seq[A] =
    foo collect {case foobar => foobar}
}

しかし、これはそうではありません:

trait Baz[A <: Foo] {
  def def3(foo: Seq[A]): Seq[A] =
    foo collect {case foobar: Bar => foobar}
}

また、これはありません:

trait Baz[A] {
  def def3(foo: Seq[A]): Seq[A] =
    foo collect {case foobar: Bar => foobar}
}

パターンマッチャーの効果のようです。特に関係ないと思いますcollect。タイプを一致ケースに追加するとすぐに、どういうわけか情報が失われます:-/

しかし、怪盗として、最初の 2 つのケースがうまくいったことに、私も実際に驚きました。Foo型推論アルゴリズムが、既知の安定した型 ( ) と型パラメーターまたは型メンバーを区別するのは (そして合理的に思える) に違いありません。コンパイラの達人に質問に答えてもらうには、scala 言語のメーリング リストで質問する必要があるかもしれません...

于 2012-06-28T01:03:31.847 に答える