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?
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.
Since Java does not know the actual element type, I found it most useful to just use
List[_]
. Then the warning goes away and the code describes reality - it is a list of something unknown.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 warningTo work around this, first create a case class:
then in the pattern matching do something like:
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
).You can use the
Typeable
type class from shapeless to get the result you're after,Sample REPL session,
The
cast
operation will be as precise wrt erasure as possible given the in-scopeTypeable
instances available.Not a solution but a way to live with it without sweeping it under the rug altogether: Adding the
@unchecked
annotation. See here - http://www.scala-lang.org/api/current/index.html#scala.uncheckedI wanted to add an answer which generalises the problem to: How do a get a String representation of the type of my list at runtime