How to pattern match on generic type in Scala?

Calin-Andrei Burloiu picture Calin-Andrei Burloiu · Apr 17, 2013 · Viewed 21.1k times · Source

Let's suppose we have a generic class Container:

case class Container[+A](value: A)

We then want to pattern match a Container with a Double and a Container of Any:

val double = Container(3.3)  
var container: Container[Any] = double

To do this, we would normally write:

container match {  
  case c: Container[String] => println(c.value.toUpperCase)
  case c: Container[Double] => println(math.sqrt(c.value))  
  case _ => println("_")  
}

However, the compiler gives two warnings, one for each of the first two cases. For example, the first warning says: "non-variable type argument String in type pattern Container[String] is unchecked since it is eliminated by erasure". Because of the erasure, it is impossible during runtime to distinguish between different kinds of containers and the first catch will be matched. As a consequence, container of type Container[Double] will be matched by the first case, which catches Container[String] objects, so toUpperCase method will be called on a Double and a java.lang.ClassCastException will be thrown.

How to match a Container parametrized by a particular type?

Answer

drexin picture drexin · Apr 17, 2013

In general rarry's answer is correct, for your case however it can be simplified, because your container only contains a single value of a generic type, so you can match on that value's type directly:

container match {
  case Container(x: String) => println("string")
  case Container(x: Double) => println("double")
  case _ => println("w00t")
}