Alex Rivera | Logout

How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections?

Asked 2009-07-07T19:03:38.917
391

It's a sad fact of life on Scala that if you instantiate a List[Int], you can verify that your instance is a List, and you can verify that any individual element of it is an Int, but not that it is a List[Int], as can be easily verified:

scala> List(1,2,3) match {
     | case l : List[String] => println("A list of strings?!")
     | case _ => println("Ok")
     | }
warning: there were unchecked warnings; re-run with -unchecked for details
A list of strings?!

The -unchecked option puts the blame squarely on type erasure:

scala>  List(1,2,3) match {
     |  case l : List[String] => println("A list of strings?!")
     |  case _ => println("Ok")
     |  }
<console>:6: warning: non variable type-argument String in type pattern is unchecked since it is eliminated by erasure
        case l : List[String] => println("A list of strings?!")
                 ^
A list of strings?!

Why is that, and how do I get around it?

Edit
Report

2 Answers

13

There is a way to overcome the type erasure issue in Scala. In Overcoming Type Erasure in matching 1 and Overcoming Type Erasure in Matching 2 (Variance) are some explanation of how to code some helpers to wrap the types, including Variance, for matching.

answered 2011-03-13T14:24:16.457
11

I found a slightly better workaround for this limitation of the otherwise awesome language.

In Scala, the issue of type erasure does not occur with arrays. I think it is easier to demonstrate this with an example.

Let us say we have a list of (Int, String), then the following gives a type erasure warning

x match {
  case l:List[(Int, String)] => 
  ...
}

To work around this, first create a case class:

case class IntString(i:Int, s:String)

then in the pattern matching do something like:

x match {
  case a:Array[IntString] => 
  ...
}

which seems to work perfectly.

This will require minor changes in your code to work with arrays instead of lists, but should not be a major problem.

Note that using case a:Array[(Int, String)] will still give a type erasure warning, so it is necessary to use a new container class (in this example, IntString).

answered 2010-12-14T19:12:02.903

Your Answer