drh*_*gen 5 scala type-inference partialfunction type-parameter
通常,在收集与特定类型匹配的序列的所有元素时,生成的集合既具有原始集合的类型,又具有为以下类型选择的类型:
trait Foo
trait Bar
trait Baz {
// Works
def def1(foo: Seq[Foo]): Seq[Foo with Bar] =
foo collect {case foobar: Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
当输入类型由有界成员类型参数化并且我想要的全部是由绑定类型(而不是成员类型)参数化的序列时,这甚至有效:
trait Baz {
type memberType <: Foo
// Works
def2(foo: Seq[memberType]): Seq[Foo with Bar] =
foo collect {case foobar: Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我真的想要返回由成员类型参数化的序列时,这会失败:
trait Baz {
type memberType <: Foo
// Fails
def def3(foo: Seq[memberType]): Seq[memberType with Bar] =
foo collect {case foobar: Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
error: type mismatch;
found : Seq[this.Foo with this.Bar]
required: Seq[Baz.this.memberType with this.Bar]
foo collect {case foobar: Bar => foobar}
Run Code Online (Sandbox Code Playgroud)
为了恢复功能,我可以在collect调用中包含成员类型,但由于签名,每个元素必须匹配该类型,这似乎是多余的:
trait Baz {
type memberType <: Foo
// Works
def def4(foo: Seq[memberType]): Seq[memberType with Bar] =
foo collect {case foobar: memberType with Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法定义一个成员类型序列,以便在collect编辑时记住它们的成员类型?
这不是答案,只是一些观察。这有效:
trait Baz[A <: Foo] {
def def3(foo: Seq[A]): Seq[A] =
foo collect {case foobar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
但这不是:
trait Baz[A <: Foo] {
def def3(foo: Seq[A]): Seq[A] =
foo collect {case foobar: Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
这也不是:
trait Baz[A] {
def def3(foo: Seq[A]): Seq[A] =
foo collect {case foobar: Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
所以这似乎是模式匹配器的效果;我不认为这有什么collect特别的关系。不知何故,一旦您将类型添加到匹配案例中,它就会丢失信息:-/
但作为凯托,我实际上也很惊讶你的前两个案例确实有效。类型推断算法必须(并且看起来合理)区分已知的稳定类型 ( Foo) 和类型参数或类型成员。您可能需要在 scala 语言邮件列表上询问,以获得一些编译器专家来回答这个问题......