Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala pattern match on classes with a typed parameter

I'm trying to pattern match on a custom class with a typed parameter:

class Foo[A]

def isMyFoo[A: ClassTag](v: Any) = v match {
    case mine: Foo[A] => "my foo"
    case other: Foo[_] => "not my foo"
    case _ => "not a foo"
}

That will not work; no matter the type of Foo, I will always get "my foo".

The only way I was able to make something like this work, is this:

class Foo[A](implicit t: ClassTag[A]) {
    val tag = t
}

def isMyFoo[A: ClassTag](v: Any) = v match {
    case foo: Foo[_] =>
        if (foo.tag == classTag[A]) "my foo"
        else "not my foo"
    case _ => "not a foo"
}

Is there a more elegant way of doing so? Do I have to keep the ClassTag inside Foo?

like image 245
Eyal Roth Avatar asked Dec 13 '25 14:12

Eyal Roth


1 Answers

Do I have to keep the ClassTag inside Foo?

Yes. The type parameter of Foo is erased at run-time, so all you know is that you have a Foo[_]. The only way around that is to save the type information using a ClassTag or TypeTag. If you're going to go this route, I would recommend using TypeTag, as you will be able to use more refined types. ClassTags still only work modulo type erasure.

For example, using a ClassTag, this is wrong:

scala> val fooListString = new Foo[List[String]]
fooListString: Foo[List[String]] = Foo@f202d6d

scala> isMyFoo[List[Int]](fooListString)
res4: String = my foo

But the following will work:

class Foo[A](implicit t: TypeTag[A]) {
    val tag = t
}

def isMyFoo[A: TypeTag](v: Any) = v match {
    case foo: Foo[_] =>
        if (foo.tag.tpe =:= typeOf[A]) "my foo"
        else "not my foo"
    case _ => "not a foo"
}

scala> val fooListString = new Foo[List[String]]
fooListString: Foo[List[String]] = Foo@6af310c7

scala> isMyFoo[List[Int]](fooListString)
res5: String = not my foo
like image 179
Michael Zajac Avatar answered Dec 15 '25 21:12

Michael Zajac



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!