2012-08-14 13 views
7

This great daily Scala article describe cómo superar la supresión de tipo en la coincidencia. Estoy intentando aplicar la técnica para transformar un IndexesSeq de tipos parametrizados, pero las coincidencias están fallando. ¿Por qué es esto y cómo puedo solucionarlo?Coincidencia de modelo de Scala con manifiesto

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

Si elimine la línea de Def luego veo líneas como

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

lo que sugiere que el _ en el constructor de análisis es el problema, pero no sé qué otra cosa que poner en ahí.

+2

¿Ha leído en el artículo de esta frase: "Es muy importante darse cuenta de la utilización de los tiposDeArgumento del manifiesto. Esto devuelve una lista de los manifiestos de cada tipo de argumento. No se puede simplemente comparar el deseado == m porque las comparaciones de los manifiestos no son profundas. Hay una debilidad en este código ya que solo maneja los genéricos que tienen 1 nivel de profundidad ". La discusión que lo rodea no le dirá exactamente cómo solucionarlo, pero debería decirle por qué no funciona. –

+0

@Rex: Me perdí en algunos de los puntos más finos del artículo, pero ahora que lo señalas veo el problema y tendré una idea sobre si puedo abordarlo de alguna otra manera. Gracias – Pengin

+1

En realidad, hay dos problemas: uno es el anidamiento y el otro es que tiene varios tipos en una lista, lo que requiere un ensanchamiento de tipo. Creo que vas a querer un 'isAssignableFrom's en la solución final, pero desafortunadamente no tengo tiempo para escribir una solución yo mismo ahora mismo. –

Respuesta

1

Gracias a los comentarios de Rex Kerr he improvisado algo que creo que funciona. Es probable que pueda hacerse más elegante/general, pero parece hacer el trabajo por ahora:

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