模式匹配函数签名与类标签/类型标签



我有一个方法,可以为不同的函数类探索不同的参数值。之前,我做了一些非类型安全的运行时检查,在擦除之后,重要的是我使用的是Function2而不是Function3。我尝试使用ClassTags/TypeTags更安全,但我仍在努力寻找一个好的解决方案。我最初的参考点是Tksfz对

的回答:

如何解决Scala上的类型擦除?或者,为什么我不能获得集合的类型参数?

import reflect.ClassTag
def matchList[A: ClassTag](list: List[A]) = list match {
  case strlist: List[String] => println("A list of strings!")
  case intlist: List[Int] => println("A list of ints!")
  case _ => println("Ok")
}

然而,我发现给出的代码片段不起作用,并且两种情况都匹配字符串列表——可能答案涉及不同版本的scala(我使用的是2.10.3)。

我发现了另一个例子,其中有人使用TypeTags给出了一个片段(我仍然有点不清楚类型标记类型之间的区别是什么;我很高兴看到RTFM对这一点的回应,只要它附有一个好的M到FR的链接。

EDIT:我前面的例子没有应用这些函数,所以匹配中产生警告的部分是没有意义的(正如第一个回答者所指出的)。我已经更新了示例,以便它更能代表我的实际问题。

package misc
import reflect.runtime.universe._
object CTDemo {
  def main(args: Array[String]) = {
    val f0v: Function2[Int, Double, String] = f0(_, _)
    val f1v: Function2[Int, (Double, Double), String] = f1(_, _)
    println(matchFunc(f0v))
    println(matchFunc(f1v))
  }
  def f0(i: Int, p: Double) = {
    s"output on $p doesn't matter"
  }
  def f1(i: Int, p: (Double, Double)) = {
    s"output on $p doesn't matter"
  }
  def matchFunc[I: TypeTag, A: TypeTag, O: TypeTag](predFunc: Function2[I, A, O]) = {
    predFunc match {
      case fs: Function2[Int, Double, String] if(typeOf[A] <:< typeOf[Double]) => {
        "Single-arg, result is: " + fs(1,2.0)
      }
      case ds: Function2[Int, (Double, Double), String] if(typeOf[A] <:< typeOf[(Double,Double)])  => {
        "Double-arg, result is: " + ds(1,(2.0,3.0))
      }
    }
  }
}

这种情况可以工作,但它仍然会抛出编译器警告。是否有一种简洁、无"asInstanceOf"、无警告和线程安全的方法来检查函数的类型签名?如果有帮助的话,我愿意升级到scala 2.11。

你的火柴没有做任何工作,所以

  def matchFunc[I: TypeTag, A: TypeTag, O: TypeTag](predFunc: Function2[I, A, O]) = {
      if (typeOf[A] <:< typeOf[Double]) {
        "Single-arg"
      } else if (typeOf[A] <:< typeOf[(Double,Double)]) {
        "Double-arg"
      }
  }

另一个习语是这样的:

scala> def g[A: reflect.ClassTag](as: List[A]) = as match { case List(_: Int) => "I" }
g: [A](as: List[A])(implicit evidence$1: scala.reflect.ClassTag[A])String
scala> g(List(3))
res4: String = I
scala> g(List(3.0))
scala.MatchError: List(3.0) (of class scala.collection.immutable.$colon$colon)
  at .g(<console>:7)
  ... 33 elided

也就是说,作为一个美化的(虽然方便的)isInstanceOf。

在Scala中,它是RTFS,其中S = spec或SIP。

最新更新