Reputation: 6081
I'm trying to achieve something like this:
def a(b: Any) = {
b match {
case x: Seq[String] => println("x")
}
}
// somewhere else
a(List("b"))
As a result I'd love to see "x" being printed, and I don't.
Basically I want to match against a type/trait and cover all of the objects whose types derive from/implement such type/trait, with the trait being Seq and the type parameter being known in advance. Since I'm a scala novice I'm quite stuck, however.
Ideas?
Upvotes: 3
Views: 1723
Reputation: 53665
My first thought is that you're doing it wrong. Instead of pattern matching, what you want here is a type class, or some other mechanism (class methods) that can do type-based dynamic dispatch. Using pattern matching to perform your own type-based dispatch makes for messy code and thwarts type safety.
Here's a quick and common example of a type class in Scala. First, define a trait that the class of types has in common:
trait Ord[T] { def compare (x: T, y: T): Boolean }
In your case, you would want the a
method to be the trait's method. Then, for each type that you want to belong to the type class, create an implicit object for it:
implicit object ordInt extends Ord[Int] {
def compare (x: Int, y: Int) = x <= y
}
Here I've made Int
an instance of my Ord
type class. Now you can write methods that rely on the interface that your type class provides. The method should accept the specific type class object implicitly, like so:
def sort[T](xs: List[T])(implicit ord: Ord[T]) = {
you can then make use of the special methods on the type class by invoking it on the implicit object.
def sort[T](xs: List[T])(implicit ord: Ord[T]) = {
def insert(y: T, ys: List[T]): List[T] = ys match {
case Nil => List(y)
case z :: zs =>
if (ord.compare(y,z)) { y::z::zs } // <--- here I use ord.compare
else { z :: insert(y, zs) }
}
xs.foldRight(List[T]())(insert _)
}
And voila! We have type-directed dispatch, without losing type safety. Want to sort a list of Ints? No problem. Trying to sort a list of something that doesn't have an Ord instance? The compiler will stop you from shooting yourself in the foot.
Upvotes: 1
Reputation: 53348
You can't check against parameterized types because of type erasure. See this question why there will be a warning: Warning about an unchecked type argument in this Scala pattern match?
Another question and its answers tell you how to get around that: How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections?
Nevertheless your code works fine, when you don't check against type parameters:
scala> List("a") match { case _: Seq[_] => 1 case _ => 2 }
res0: Int = 1
Upvotes: 5