I have 3 traits
trait A
trait B
trait AB extends A with B
and a method
def collect[E: Manifest](list: List[Any]) =
list flatMap {
case record: E => Some(record)
case _ => None
}
For the given list
val list = new A {} :: new A {} :: new A with B {} :: new AB {} :: Nil
I invoked collect
with different types
collect[A with B](list) // collect all elements from the list
collect[AB](list) // collect only the last element
Could anyone explain the difference in behavior for A with B
and AB
types?
It is highly unintuitive but it conforms to the specification. First, quoting from the Manifest docs (emphasis mine):
So in
collect[A with B]
we are matching the erasure ofA with B
. And what is that? if we look at the Type erasure section of the spec, we read:and the intersection dominator is defined as (again, emphasis mine)
In our case the subsequence is
A,B
as they don't have any subtyping relationship, and thus the erasure ofA with B
isA
, so that incollect[A with B]
we are actually matchingA
.You can easily see this behavior by looking at the output of
collect[B with A]
, and/or adding anew B {}
to yourlist
.