Following my previous question came a quick and great answer, however it turned out my example didn't match my actual production code well enough. In summary I'm in need of a new implementation of the collect method.
The second fruit world (with some pretty funky fruit trees):
class Fruit {
var seeds:Array[Fruit] = Array()
def naiveCollect[F <: Fruit]:Array[Fruit] = this match {
case f:F => Array(this)
case _ => seeds.map(_.select[F]).flatten.toArray
}
}
class Apple extends Fruit
class Pear extends Fruit
class GrannySmith extends Apple
Does not work because of type erasure:
var tree = new Fruit { seeds = Array(
new Apple,
new Pear,
new GrannySmith,
new Pear { seeds = Array(
new Apple,
new Pear)},
new Apple)}
scala> tree.naiveCollect[Apple]
res1: Array[Fruit] = Array($anon$2@5a4b99fa)
// wanted output: Apple, GrannySmith, Apple, Apple
EDIT, SOLUTION1:
Turns out i managed to produce something which works by using the PartialFunction as in the std lib.
class Fruit {
...
def clumsyCollect[F](pf:PartialFunction[Fruit, F]):Seq[F] =
if (pf.isDefinedAt(this))
List(pf(this))
else
seeds.flatMap(_.selectPartial[F](pf))
}
Use case:
tree.clumsyCollect { case a:Apple => a }
Any alternatives or tips on cleaning this up would still be great though!