Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala "does not take parameters" when pattern-matching parametric case-class

Tags:

scala

I have the following code:

sealed trait A

case class B[T](v: T) extends A
case class C[T](v: T) extends A

object Test {
  def swap(a: A): A = a match {
    case a: B[t] => C[t](a.v) // works!
    case C[t](v) => B[t](v) // error: C[t] does not take parameters
  }
}

I would expect either both cases to fail or both of them to work. What's the meaning of the error for the second case? Is there a syntax destructuring parametric case-classes?

Note: Here, 't' in lower case is essential. If it were 'T', the checker would be looking for it in the type parameters of the method.

like image 862
comco Avatar asked Apr 29 '14 22:04

comco


1 Answers

When you do a match { case C(v) => ??? }, you actually call unapply method of the C companion object, something like this: C.unapply(a) match {Some(v) => ???}

There is only one C object, not an entire family of C[t]. There is no object you can refer to as C[Int], so case C[t](v) => doesn't make sense.

In your example, you use B[t] as a type, not as a pattern, and that's why it works. Note that while the match may succeed, you won't get anything in t, because of type erasure.

When you call C[t](a.v), then first of all, compiler erases type t anyway, and second, this is rewritten to a call to apply method on the companion object: C.apply[t](a.v). Note that the type parameter is on the method call, not on the object.

like image 61
Karol S Avatar answered Oct 15 '22 14:10

Karol S