2012-08-14 87 views
7

This great daily Scala article描述瞭如何克服匹配中的類型擦除。我試圖應用該技術來轉換IndexesSeq的參數化類型,但匹配失敗。爲什麼是這樣,我該如何解決它?與清單匹配的Scala模式

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)) 
    )) 
} 

如果我取消的防守線,然後我看不出紋路如

prototype.Example$TableColumn[_ <: Any], prototype.Example$TableColumn[Int] 

提示_在分析構造的問題,但我不知道該怎麼把別人的那裏。

+2

您是否在文章中讀過這句話:「注意清單的typeArguments的使用是至關重要的。這將返回每個類型參數的清單列表,因爲清單比較不深,所以不能簡單地比較所需的== m。該代碼中存在一個弱點,它只能處理深度爲1級的泛型。周圍的討論不會告訴你如何修正它,但它應該告訴你爲什麼它不起作用。 – 2012-08-14 18:05:24

+0

@Rex:我迷失在文章的一些細節中,但現在你指出了我看到的問題,並且會考慮是否可以用其他方式解決它。謝謝 – Pengin 2012-08-14 18:11:30

+1

實際上有兩個問題:一個是嵌套,另一個是你在一個列表中有多個類型,這需要類型加寬。我想你會在最終的解決方案中需要一些'isAssignableFrom',但不幸的是我現在沒有時間自己寫一個解決方案。 – 2012-08-14 18:24:36

回答

1

感謝雷克斯克爾的評論,我拼湊出了一些我認爲有效的東西。它可能可以做得更優雅/一般,但它似乎現在完成了這項工作:

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)) 
    )) 
}