【问题标题】:Scala: Have the type parameter of a collection survive a "collect" when the type parameter is a member typeScala:当类型参数是成员类型时,让集合的类型参数在“收集”中存活
【发布时间】:2012-06-27 14:42:32
【问题描述】:

通常,当收集与特定类型匹配的序列的所有元素时,生成的集合既有原始集合的类型,也有为以下选择的类型:

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}
}

有没有办法定义成员类型的序列,以便他们在collected 时记住他们的成员类型?

【问题讨论】:

  • 已检查该代码是否有警告?由于memberType 是抽象的,它在foobar: memberType with Bar 检查中被删除。
  • 我有点困惑为什么 1 和 2 甚至可以工作。收集的序列只是一个 Seq[Bar],但编译器仍然允许将其键入为 Seq[Foo with Bar]。好吧,我想我更困惑为什么这不会导致擦除警告。
  • 我在运行任何工作示例时都没有看到任何警告。类型擦除会对最后一个示例产生任何影响(已对其进行编辑以正确指示它“有效”)?
  • 这很奇怪,但如果你把 Baz 变成一个类,它确实会显示警告。

标签: scala type-inference type-parameter partialfunction


【解决方案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 语言邮件列表中询问,以获得一些编译器专家来回答问题...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-07
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    相关资源
    最近更新 更多