This great daily Scala article describes how to overcome type erasure in matching. I'm trying to apply the technique to transform an IndexesSeq of parameterised types, but the matches are failing. Why is this, and how can I fix it?
object Example extends App{
class TableColumn[T](
val values: IndexedSeq[T],
val name: Option[String] = None
)(implicit val m: Manifest[T])
class Def[C](implicit desired : Manifest[C]) {
def unapply[X](c : X)(implicit m : Manifest[X]) : Option[C] = {
//println("m.toString+", "+desired.toString)
def sameArgs = desired.typeArguments.zip(m.typeArguments).forall {
case (desired,actual) => desired >:> actual
}
if (desired >:> m && sameArgs) Some(c.asInstanceOf[C])
else None
}
}
val IntTableColumn = new Def[TableColumn[Int]]
val DoubleTableColumn = new Def[TableColumn[Double]]
class Analysis(data: IndexedSeq[TableColumn[_]]){
val transformedData = data.map{_ match{
case IntTableColumn(tc) => println("Column of Int! "+ tc)
case DoubleTableColumn(tc) => println("Column of Double! "+ tc)
case _ => println("no match")
}}
}
new Analysis(IndexedSeq(
new TableColumn(IndexedSeq(1,2,3)),
new TableColumn(IndexedSeq(1.0,2.0,3.0))
))
}
If I uncomment the line in Def then I see lines such as
prototype.Example$TableColumn[_ <: Any], prototype.Example$TableColumn[Int]
suggesting that the _ in the Analysis constructor is the problem, but I don't know what else to put in there.
Thanks to comments from Rex Kerr I've cobbled together something that I think works. It can probably done more elegantly/generally, but it seems to get the job done for now:
object Example extends App{
class TableColumn[T](
val values: IndexedSeq[T],
val name: Option[String] = None
)(implicit val m: Manifest[T])
class TableColumnMatcher[T](implicit desired: Manifest[T]){
def unapply(tc: TableColumn[_]): Option[TableColumn[T]] = {
if(tc.m == desired) Some(tc.asInstanceOf[TableColumn[T]])
else None
}
}
object TableColumnMatcher{
lazy val IntTC = new TableColumnMatcher[Int]
lazy val DoubleTC = new TableColumnMatcher[Double]
}
class Analysis(data: IndexedSeq[TableColumn[_]]){
import TableColumnMatcher._
val transformedData = data.map{_ match{
case IntTC(tc) => println("Column of Ints!");
case DoubleTC(tc) => println("Column of Doubles!")
case _ => println("no match")
}}
}
new Analysis(IndexedSeq(
new TableColumn(IndexedSeq(1,2,3)),
new TableColumn(IndexedSeq(1.0,2.0,3.0))
))
}
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