Normally, when collecting all the elements of a sequence that match a particular type, the resulting collection has both the type of the original collection and the type selected for:
trait Foo
trait Bar
trait Baz {
// Works
def def1(foo: Seq[Foo]): Seq[Foo with Bar] =
foo collect {case foobar: Bar => foobar}
}
This even works when the the input type is parameterized by a bounded member type and all I want back is a sequence parameterized by the bound type (not the member type):
trait Baz {
type memberType <: Foo
// Works
def2(foo: Seq[memberType]): Seq[Foo with Bar] =
foo collect {case foobar: Bar => foobar}
}
However, this fails when I actually want back a sequence parameterized by the member type:
trait Baz {
type memberType <: Foo
// Fails
def def3(foo: Seq[memberType]): Seq[memberType with Bar] =
foo collect {case foobar: Bar => foobar}
}
Error message:
error: type mismatch;
found : Seq[this.Foo with this.Bar]
required: Seq[Baz.this.memberType with this.Bar]
foo collect {case foobar: Bar => foobar}
To recover functionality, I can include the member type in the collect
call, but that seems redundant given that every element has to match that type because of the signature:
trait Baz {
type memberType <: Foo
// Works
def def4(foo: Seq[memberType]): Seq[memberType with Bar] =
foo collect {case foobar: memberType with Bar => foobar}
}
Is there a way to define a sequence of member types so that they remember their member types when collect
ed?
This is not answer, but just some observation. This works:
trait Baz[A <: Foo] {
def def3(foo: Seq[A]): Seq[A] =
foo collect {case foobar => foobar}
}
but this not:
trait Baz[A <: Foo] {
def def3(foo: Seq[A]): Seq[A] =
foo collect {case foobar: Bar => foobar}
}
also this not:
trait Baz[A] {
def def3(foo: Seq[A]): Seq[A] =
foo collect {case foobar: Bar => foobar}
}
so it seems to be an effect of the pattern matcher; I don't think it has anything to do with collect
in particular. Somehow it looses information as soon as you add the type to the match case :-/
But as Kaito, I was actually surprised, too, that your first two cases did work. It must be (and seems reasonable) that the type inference algorithm makes a difference between a known stable type (Foo
) and a type parameter or type member. You might need to ask on the scala language mailing list to get some of the compiler gurus to answer the question...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With