read

Due to the type erasure in Scala I got problems when I tried to create a function filterType<T>(list: List[Any]): List[T] that simply filters out all elements in a list of type T. This is the naive implementation that I first tried out:

object TypeFiltering {
  def typeFilter[T](list: List[Any]): List[T] = list.filter {
	_ match {
	  case _: T => true
	  case _ => false
	}}.asInstanceOf[List[T]]
  def main(args: Array[String]) {
	val list = List(1,2,3,"a","b","c")
	println("strings: " + typeFilter[String](list))
	println("bools: " + typeFilter[Boolean](list))
  }
}
/*
Output:
strings: List(1, 2, 3, a, b, c)
bools: List(1, 2, 3, a, b, c)
*/

What happened here is essentially that the type erasure mechanism that exists both in Java and Scala (but not in C♯) removes the type T from the following line:

case _: T => true

What’s left is just the following, which obviously will always match.

_ => true

I consulted the very helpful Scala community at irc.freenode.net/#scala and got the suggestion that I should use the undocumented and still experimental Scala manifests. Jorge Ortiz has written a very instructive blog post about what manifests are and how you use them. I ended up with this typeFilter function:

def typeFilter[T](l:List[Any])(implicit m:scala.reflect.Manifest[T]) =
	l.filter{x:Any => m.erasure.isInstance(x)}.asInstanceOf[List[T]]
/*
Output:
strings: List(a, b, c)
bools: List()
*/
Blog Logo

André Laszlo


Published

Back to Overview