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特别无关。一旦您将类型添加到匹配案例中,它就会以某种方式丢失信息:-/

但作为 Kaito,我实际上也很惊讶你的前两个案例确实有效。类型推断算法必须(并且似乎合理)在已知的稳定类型 ( Foo) 和类型参数或类型成员之间产生差异。您可能需要在 scala 语言邮件列表中询问,以获得一些编译器专家来回答这个问题......

于 2012-06-28T01:03:31.847 回答