不同类型的Seq

时间:2015-05-22 18:01:50

标签: scala

我有3个函数,kk expect Array[Byte]List[Array[Byte]],所以我做了一个模式匹配,

def gg (a :Array[Byte]) = "w"
def ff (a :List[Array[Byte]]) = "f"

def kk(datum : Any) = datum match {
  case w : Array[Byte] => gg(w)
  case f :List[Array[Byte]] => ff(f)
  case _ => throw new Exception("bad data")
}

我尝试编译代码时遇到错误:

  

非变量类型参数类型模式中的List [Any] List [List [Any]](List [List [Any]]的基础)未被选中,因为它被删除删除

所以我将kk函数构造为流动,现在可以编译:

def kk(datum : Any) = datum match {
  case w : Array[Byte] => gg(w)
  case f :List[_] => ff(f.asInstanceOf[List[Array[Byte]]])
  case _ => throw new Exception("bad data")}

我的问题: 1:是我当前版本的kk是用于为List做模式匹配的惯用方法,如果没有,有人可以展示如何做到这一点吗?

2:如果我想模式匹配List[Any]List[List[Any]],我怎么能这样做?如果我的数据类型为(ff(f.asInstanceOf[List[Array[Byte]]])

List[Byte]可能会导致错误

1 个答案:

答案 0 :(得分:1)

有几件事要说:

  1. 类型擦除有时候很重要。尝试在this question
  2. 中获得洞察力
  3. 需要这样的功能可能是由其他地方的糟糕设计造成的。 TList[T]很少用作替代品。如果是您的情况,请尝试将它们带到至少Either或更具体的案例类别。
  4. 如果您确实Any没有任何其他预先安排好的知识而且您确实需要确定List[Byte]List[List[Byte]],那么您唯一的选择就是检查像这样的集合:

    class ListMatch[A](f: Any => Option[A]) {
      def unapply(obj: Any) = obj match {
        case seq: List[_] =>
          seq.foldLeft[Option[List[A]]](Some(Nil)) {
            (optSeq, elem) => for {
              seq <- optSeq
              elem <- f(elem)
            } yield elem :: seq
          } map (_.reverse)
        case _ => None
      }
    }
    
    val matchByte: PartialFunction[Any, Byte] = {
      case b: Byte => b
    }
    
    val ByteList = new ListMatch(matchByte.lift)
    val ByteListList = new ListMatch(ByteList.unapply)
    

    因此您将更改定义为

    def kk(datum: Any) = datum match {
      case ByteList(w) => gg(w)
      case ByteListList(f) => ff(f)
      case _ => "bad data"
    }
    

    您可以尝试以下测试以确保正确性:

    kk(1)  // bad data
    kk(List(1.toByte)) // w
    kk(List(List(1.toByte))) // f
    kk(List(1.toByte, 2)) // bad data
    kk(List(1.toByte), List(2)) // bad data