2
votes

I want to pattern match items in a tuple, where the items have the same type, including the type parameter. My use-case is fairly complex, but I've tried to extract a minimal example here to illustrate the problem:

class Foo[T] { }

val input = ( new Foo[String], new Foo[String] )

input match {
  case (a:Foo[x], b:Foo[x]) =>
    // Do things that rely on a and b having exactly the same type
}

But this doesn't compile, because I'm using x in the case statement twice. The compile gives the following error:

error: x is already defined as type x

I've tried changing the match to pull out different type parameters for the two inputs and then testing their equality:

input match {
  case (a:Foo[x], b:Foo[y]) if (x == y) =>
    // Do things that rely on a and b having exactly the same type
}

But that doesn't compile, giving the error

error: not found: value x

Is there some Scala syntax that I can use to match two things as having the same, unspecified, type? I am running Scala 2.9.2

1
the error message is misleading. the real error is that x is not a type.ben

1 Answers

1
votes

You should think twice any time you catch yourself using a type or type variable in a pattern match, first because type erasure means it's not likely to work, and second because parametricity means it shouldn't. There's almost always a better solution.

In this case you could do something like the following:

class Foo[T] { }

val input = (new Foo[String], new Foo[String])

def doSomething[A](pair: (Foo[A], Foo[A])) = ???

Now doSomething(input) will compile, but doSomething((new Foo[Char], new Foo[Int])) won't (assuming you leave the type parameter on Foo invariant). There's still not a lot you can (honestly) do with the items in the pair, since you only know that they have the same type, so usually you'll want to add something like a type class constraint, and using a method also helps in that respect.