【问题标题】:Scala pattern matching with manifestScala 模式与清单匹配
【发布时间】:2012-08-14 16:49:49
【问题描述】:

This great daily Scala article 描述了如何克服匹配中的类型擦除。我正在尝试应用该技术来转换参数化类型的 IndexesSeq,但匹配失败。为什么会这样,我该如何解决?

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

如果我在 Def 中取消注释该行,那么我会看到诸如

之类的行
prototype.Example$TableColumn[_ <: Any], prototype.Example$TableColumn[Int]

建议分析构造函数中的 _ 是问题所在,但我不知道还有什么可以放在那里。

【问题讨论】:

  • 您是否在文章中读到了这句话:“注意清单的 typeArguments 的使用至关重要。这将返回每个 typeArgument 的清单列表。您不能简单地比较期望 == m 因为清单比较不深。这段代码有一个弱点,它只处理 1 级深的泛型。”?周围的讨论不会准确地告诉你如何解决它,但它应该告诉你为什么它不起作用。
  • @Rex:我迷失了文章的一些细节,但现在你指出我看到了问题,并会考虑是否可以通过其他方式解决它。谢谢
  • 其实有两个问题:一个是嵌套,另一个是你在一个列表中有多个类型,需要类型加宽。我认为您会在最终解决方案中需要一些isAssignableFroms,但不幸的是我现在没有时间自己编写解决方案。
  • 既然您已经找到答案,您应该回答您自己的问题,以免它显示为未回答。

标签: scala pattern-matching type-erasure


【解决方案1】:

感谢 Rex Kerr 的 cmets,我拼凑了一些我认为可行的东西。它可能可以更优雅/更一般地完成,但现在似乎可以完成工作:

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

【讨论】:

    猜你喜欢
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 2021-12-17
    • 2011-04-16
    • 1970-01-01
    • 2014-09-30
    相关资源
    最近更新 更多