如何模式匹配Scala中的函数?

时间:2015-11-14 13:01:13

标签: scala

是否可以在scala中模式匹配函数?特别是函数的返回类型。

这是一个例子。如果函数的返回类型是Shoe或Bag,我正在尝试打印Shoe。

object Test extends App {

  trait ProductItem {
    val name: String
    val price: Int
  }

  case class Product(partialPerson: (String) => ProductItem)
  case class Shoe(name: String)(val price: Int) extends ProductItem
  case class Bag(name: String)(val price: Int) extends ProductItem

  val shoe = Shoe("nike")(_)
  val bag = Bag("addidas")(_)

  def printType(shoe: (Int) => ProductItem): Unit = {
    shoe match {
      case isShoe: ((Int) => Shoe) =>
        println("Is a shoe")
      case isBag: ((Int) => Bag) =>
        println("Is a bag")
    }
  }

  printType(shoe)
  printType(bag)
}

输出:
是鞋子 是鞋子

预期输出:
是鞋子 是一个包

2 个答案:

答案 0 :(得分:5)

这是由编译时的类型擦除引起的:

<console>:17: warning: non-variable type argument Bag in type pattern Int => Bag is unchecked since it is eliminated by erasure

您可以使用TypeTags

解决此问题
def printType[T](shoe: (Int) => T)(implicit tag: TypeTag[T]): Unit = {
    shoe match {
      case isShoe if tag.tpe =:= typeOf[Shoe]=>
        println("Is a shoe")
      case isBag if tag.tpe =:= typeOf[Bag] =>
        println("Is a bag")
    }
}

答案 1 :(得分:2)

编译此代码时,您会收到编译器警告,以解释问题 -

  

警告:(20,25)非变量类型参数c.n.p.Shoe in type   模式Int =&gt; s.n.p.Shoe是不受限制的,因为它被淘汰了   擦除         case isShoe :( Int =&gt; Shoe)=&gt;                           ^

围绕它的可能解决方案 -

  def printType[T <: ProductItem : ClassTag](item: Int => T): Unit = {
    implicitly[ClassTag[T]] match {
      case ClassTag(s) if s == classOf[Shoe] =>
        println("Is a shoe")
      case ClassTag(b) if b == classOf[Bag] =>
        println("Is a bag")
    }
  }

要理解这个解决方案,您必须熟悉隐式参数&amp; ClassTag类型。