function - scala 模式匹配函数 - 如何绕过类型删除

标签 function scala pattern-matching scala-2.11

我想要模式匹配一​​个函数,问题是类型删除。请注意,在下面的代码片段中,尽管发出了警告,但仍然发生了匹配,并且出现了“错误”的匹配。

scala> def f1 = ()=>true
f1: () => Boolean

scala> val fl = f1
fl: () => Boolean = <function0>

scala>

scala> fl match {
     | case fp :Function0[Boolean] => 1
     | case _ => 2
     | }
res8: Int = 1

scala>

scala> fl match {
     | case fp :Function0[String] => 1
     | case _ => 2
     | }
<console>:11: warning: fruitless type test: a value of type () => Boolean cannot also be a () => String (but still might match its erasure)
              case fp :Function0[String] => 1
                       ^
res9: Int = 1

scala>

我能想到的是一个包装该函数的案例类。我得到了类型安全,请注意下面的错误。 但是,首先,这是不优雅的,其次,我不明白案例类如何强制类型,而模式匹配却不能。我唯一的猜测是案例类受编译器保护,并且匹配仅在运行时解析

scala> case class FunctionWrapper(fn: ()=>Boolean)
defined class FunctionWrapper

scala> val fw = FunctionWrapper(fl)
fw: FunctionWrapper = FunctionWrapper(<function0>)

scala> def fs = ()=>"whatever"
fs: () => String

scala> val fws = FunctionWrapper(fs)
<console>:10: error: type mismatch;
 found   : () => String
 required: () => Boolean
       val fws = FunctionWrapper(fs)
                                 ^

scala> fw match {
     | case FunctionWrapper(f) => f()
     | case _ => false
     | }
res10: Boolean = true

总而言之,我想知道是否有一种优雅的方法来模式匹配函数,并且也许理解为什么上面的示例会这样做

最佳答案

简短的回答:您必须通过使用 TypeTag 来具体化类型来撤消删除。

I don't understand how the case class can enforce types whereas the pattern match can't.

因为你的案例类没有类型参数。仅删除泛型类型,这就是为什么它被称为“部分删除”。

相关问题:Generic unapply method for different types of List 。以下代码本质上与其中的答案之一相同,但使用函数而不是列表:

import scala.reflect.runtime.universe._

def foo[A : TypeTag](a: A): Int = typeOf[A] match {
  case t if t =:= typeOf[Int => Int] => a.asInstanceOf[Int => Int](0)
  case t if t =:= typeOf[Boolean => Int] => a.asInstanceOf[Boolean => Int](true)
  case _ => 3
}

foo((i: Int) => i + 1)
// res0: Int = 1

foo((b: Boolean) => if (b) 2 else 0)
// res1: Int = 2

foo((b: Boolean) => !b)
// res2: Int = 3

我不确定是否有办法编写一个提取器来使匹配 block 更好。

如果您需要以丢失静态类型信息的方式传递这些函数(将它们插入 Function[_, _] 集合,然后将其用作 Akka 消息等),那么您还需要传递标签:

import scala.reflect.runtime.universe._

case class Tagged[A](a: A)(implicit val tag: TypeTag[A])

def foo[A, B](tagged: Tagged[A => B]): Int = tagged.tag.tpe match {
  case t if t =:= typeOf[Int => Int] => tagged.a.asInstanceOf[Int => Int](0)
  case t if t =:= typeOf[Boolean => Int] => tagged.a.asInstanceOf[Boolean => Int](true)
  case _ => 3
}
foo(Tagged((i: Int) => i + 1))
// res0: Int = 1

foo(Tagged((b: Boolean) => if (b) 2 else 0))
// res1: Int = 2

foo(Tagged((b: Boolean) => !b))
// res2: Int = 3

关于function - scala 模式匹配函数 - 如何绕过类型删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32246734/

相关文章:

python - python 中的合成函数

javascript - 对象方法被视为字符串

javascript - 如何计算行单元格表中的值

f# - 如何在 F# 中比较 x 和 y?

python - 如何使用正则表达式删除python字符串中的特定模式?

javascript - 如何使用 Polymer 1.0 上的观察者通过 onclick 函数将日期从一个组件发送到另一个组件? (不使用本地存储)

java - 从 Java 访问 scala.None

scala - 为什么用 Option 包装泛型方法调用会延迟 ClassCastException?

java - Fork-join 中的内存可见性

algorithm - 算法选择建议