Is there a way to generalize this code with generics?
object ListInt {
def unapply(o: Any): Option[List[Int]] = o match {
case lst: List[_] if(lst.forall(_.isInstanceOf[Int])) =>
Some(lst.asInstanceOf[List[Int]])
case _ => None
}
}
object ListDouble {
def unapply(o: Any): Option[List[Double]] = o match {
case lst: List[_] if(lst.forall(_.isInstanceOf[Double])) =>
Some(lst.asInstanceOf[List[Double]])
case _ => None
}
}
object ListString {
def unapply(o: Any): Option[List[String]] = o match {
case lst: List[_] if(lst.forall(_.isInstanceOf[String])) =>
Some(lst.asInstanceOf[List[String]])
case _ => None
}
}
val o: Any = List("a", "b", "c")
o match {
case ListInt(lst) => println(lst.sum)
case ListDouble(lst) => println(lst.product)
case ListString(lst) => println(lst.mkString("(", ", ", ")"))
case _ => println("no match")
}
abstract class ListExtractor[A](implicit ct: reflect.ClassTag[A]) {
def unapply(o: Any): Option[List[A]] = o match {
case lst: List[_] if (lst.forall(ct.unapply(_).isDefined)) =>
Some(lst.asInstanceOf[List[A]])
case _ => None
}
}
object ListInt extends ListExtractor[Int ]
object ListString extends ListExtractor[String]
val o: Any = List("a", "b", "c")
o match {
case ListInt (lst) => println(lst.sum)
case ListString(lst) => println(lst.mkString("(", ", ", ")"))
case _ => println("no match")
}
It seems TypeTag is the way to go:
import scala.reflect.runtime.universe._
def foo[A: TypeTag](lst: A) = typeOf[A] match {
case t if t =:= typeOf[List[Int]] => lst.asInstanceOf[List[Int]].sum
case t if t =:= typeOf[List[Double]] => lst.asInstanceOf[List[Double]].product
case t if t =:= typeOf[List[String]] => lst.asInstanceOf[List[String]].mkString("(", ", ", ")")
}
println(foo(List("a", "b", "c")))
Check this excellent post for detailed explanation:
Scala: What is a TypeTag and how do I use it?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With