scala - 带有 ClassTags/TypeTags 的模式匹配函数签名

标签 scala scala-2.10

我有一种方法可以探索不同类函数的不同参数值。以前,我做了一些非类型安全的运行时检查,其中,删除后,重要的是我使用的是 Function2 还是 Function3。我已经尝试使用 ClassTags/TypeTags 来更安全一些,但我仍在努力寻找一个好的解决方案。我原来的引用点是
tksfz 的回答:

How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections?

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 的链接)。

编辑 :我之前的例子没有应用这些函数,所以产生警告的匹配部分是毫无意义的(正如第一个回答者指出的那样)。我已经更新了示例,使其更能代表我的实际问题。
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。

关于scala - 带有 ClassTags/TypeTags 的模式匹配函数签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25141469/

相关文章:

ScalaFiddle 除以零

json - 在 Play Framework Scala 中列出 Json

bash - 使用scala通过ssh远程发出命令的问题

scala - 如何为具有单个可为空成员的案例类编写 Play JSON 写入转换器

scala - "return this"在返回实际类型的协变特征中

scala - 如何使用 spark 生成大量随机整数?

scala - 如何使用反射实例化 Scala 对象

sbt - specs2-embedmongo 与 Scala 2.10.1 和 Play 2.1.1 的未解决依赖关系

scala - 在迭代器列表上延迟这个 flatMap

scala - 求和类型的标准名称,如 Either,但适用于 3 种情况?