【问题标题】:Scala Pattern Matching on Different type of Seq [duplicate]Scala模式匹配不同类型的Seq [重复]
【发布时间】:2015-08-04 20:32:00
【问题描述】:

我有 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[List[Any]](List[List[Any]] 的底层)中的非变量类型参数 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]] 进行模式匹配,我该怎么做?如果我的数据类型为List[Byte](ff(f.asInstanceOf[List[Array[Byte]]]) 可能会导致错误)

【问题讨论】:

  • 感谢您的帖子,我认为stackoverflow.com/questions/12218641/… 也是一个好地方。
  • 阅读后,新代码应如下所示: def gg (a :Array[Byte]) = "w" def ff (a :List[Array[Byte]]) = "f" def binaryDecodexx[A : TypeTag](datum : A) = typeOf[A] match { case t if t =:= typeOf[Array[Byte]] => gg(datum.asInstanceOf[Array[Byte]]) case t if t =:= typeOf[List[Array[Byte]]] => ff(datum.asInstanceOf[List[Array[Byte]]]) // case w : Array[Byte] => gg(w) // case f :列表[_] => }

标签: scala


【解决方案1】:

有几件事要说:

  1. 类型擦除有时是一件繁重的事情。尝试在this question 中获得您的洞察力
  2. 需要这样的功能可能是由其他地方的糟糕设计引起的。 TList[T] 很少用作替代品。如果是您的情况,请尝试将他们带到至少 Either 或更具体的案例类别。
  3. 如果您确实拥有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
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 2013-03-17
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    相关资源
    最近更新 更多