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.