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

2024-01-17

我想模式匹配一​​个函数,问题是类型擦除。请注意下面的代码片段,尽管warning发出了一场比赛,并且出现了“错误”的比赛。

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>

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

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.

我不明白案例类如何强制类型,而模式匹配却不能。

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

相关问题:不同类型List的通用unapply方法 https://stackoverflow.com/questions/16885199/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

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

如果您需要以丢失静态类型信息的方式传递这些函数(将它们推入集合中)Function[_, _],使用 then 作为 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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scala 模式匹配函数 - 如何绕过类型擦除 的相关文章

  • Spark RDD默认分区数

    版本 Spark 1 6 2 Scala 2 10 我正在执行以下命令spark shell 我试图查看 Spark 默认创建的分区数量 val rdd1 sc parallelize 1 to 10 println rdd1 getNum
  • 在 SQLServer 2005 函数中执行动态 SQL

    我在回答这个问题时会说 我不认为这是可以解决的 我还有一个解决方法 我可以创建一个带有输出的存储过程来完成此操作 使用函数对需要此校验和的部分进行编码会更容易 该代码将不起作用 因为Exec SP ExecuteSQL SQL来电 有人知道
  • 重塑案例类构造函数?

    试图找到一种方法来 重塑 案例构造函数以填充某些默认值 以下情况可能吗 def reshape T R1 lt HList R2 lt HList h R1 R2 gt T example case class MyClass a Doub
  • 为什么 C++ 对于 new 和 delete 有其单独的语法?

    为什么不能只是常规的函数调用 新本质上是 malloc sizeof Foo Foo Foo 虽然删除是 Foo Foo free 那么为什么 new delete 最终会拥有自己的语法而不是常规函数呢 这是一个尝试 The new操作员呼
  • 函数名前的星号有什么作用?

    我对在大多数具有我不熟悉的函数声明的 C 程序中看到的内容感到困惑 void func name void param 什么是 暗示该功能 我的理解 在变量类型中的特点是它创建一个指向另一个变量的指针 因此它可以跟踪后一个变量存储在内存中的
  • 如何使用 apply/unapply 方法重现案例类行为?

    我尝试用普通类和伴生对象替换案例类 但突然出现类型错误 编译良好的代码 综合示例 trait Elem A B def C other Elem C A Elem C B other match case Chain head tail g
  • Java / Scala Future 由回调驱动

    简洁版本 我怎样才能创建一个Promise
  • Scala:具有复杂结构的树插入尾递归

    我正在 scala 中创建自定义对象树 并且我的插入方法引发堆栈溢出 因为它不是尾递归 但是 我不太清楚如何使其尾递归 我见过使用 累加器 变量的相关示例 但它们要么是只能相乘和覆盖的整数之类的东西 要么是我在适应树时遇到困难的列表 这是我
  • Scala Array.apply 有何魔力

    来自 scala 2 10 4 的 array scala Array定义为 final class Array T length Int extends java io Serializable with java lang Clonea
  • 函数输入参数的 auto 是否可以替代函数模板?

    在 C 20 中auto关键字可用于函数输入参数 这是函数模板的适当替代吗 在决定采用哪种方法时是否需要考虑任何实际差异 template
  • 获取ERLANG中的最长公共子序列

    我是这个 ERLANG 的新手 我了解基础知识 这就像计划 但范围更广 我知道如何创建一个函数 但在创建一个获取最长公共子序列的函数时遇到问题 lcs str1 str2 是一个接受两个字符串并输出一个整数的函数 lcs algorithm
  • 使用 Spray-json 解析简单数组

    我正在尝试 但失败了 了解 Spray json 如何将 json feed 转换为对象 如果我有一个简单的 key gt value json feed 那么它似乎可以正常工作 但是我想要读取的数据出现在如下列表中 name John a
  • Scala:类似 Option (Some, None) 但具有三种状态:Some、None、Unknown

    我需要返回值 当有人询问值时 告诉他们以下三件事之一 这是值 没有价值 我们没有关于该值的信息 未知 情况 2 与情况 3 略有不同 示例 val radio car radioType 我们知道该值 返回无线电类型 例如 pioneer
  • 如何捕获 Oozie Spark 输出

    有没有办法捕获spark的输出然后将其输入到shell上 我们当前正在使用 scala 创建 jar 文件 并希望我们的 Spark 输出成为 shell 输入 我的想法是使用 wf actionData spark XXXX var 我只
  • strlen(s) 和 (strlen)(s) 之间有什么区别吗? [复制]

    这个问题在这里已经有答案了 在 bstrlib c bstring 库 中 有几个地方在函数调用周围放置了括号 什么目的 代码片段 bstring bfromcstr const char str bstring b int i size
  • 如何在 Scala 中打印任何内容的列表?

    目前我有一个打印整数的方法 def printList args List Int Unit args foreach println 我如何修改它 使其足够灵活 可以打印任何内容的列表 您不需要专用的方法 所需的功能已经在集合类中 pri
  • Scala 和变量中的模式匹配

    我是 Scala 新手 有点想知道模式匹配是如何工作的 想象一下我有以下内容 case class Cls i Int case b Cls i gt Ok case e Cls gt Ok case f Cls gt Ok case s
  • Scala 模式匹配变量绑定

    为什么提取器返回时不能以 样式绑定变量Option
  • Spark Scala 将列从一个数据帧复制到另一个数据帧

    我有一个原始数据框的修改版本 我在其上进行了聚类 现在我想将预测列恢复为原始 DF 索引没问题 因此匹配 我该怎么做 使用这段代码我得到一个错误 println Predicted dfWithOutput show println Ori
  • 比较数组中的文件、从文本文件中删除行、函数、日志记录

    所以我创建了这两个数组 Approved Shares 和 Current Shares Reads Approvedshare txt and makes the txt file into an array public objFSO

随机推荐

  • python 中的动态 numpy 数组

    我正在尝试创建一个形状为 a b 1 d 的 numpy 数组 假设 A 其中 d 未知并根据我的输入而变化 我有另一个形状为 a b 1 1 的数组 假设为 B 我想将 for 循环中的 B 值附加到 A 中 在 matlab 中 可以通
  • 如何在 postgres 中使用 \timing

    我想知道在 Postgres 中执行查询所需的时间 我看到很多建议使用的答案 timing 但我是 Postgres 的新手 我不知道如何使用它 您可以使用 timing仅使用命令行客户端psql 因为这是一个psql命令 它是一个打开和关
  • PyQt5 - 如何从工作线程发出信号以通过 GUI 线程调用事件

    正如我在标题中提到的 我怎样才能做这样的事情 class Main QWidget def init self super init def StartButtonEvent self self test ExecuteThread sel
  • Swift - 无条件动态转换类?

    我似乎无法将泛型类型转换为另一个类型 Swift 抛出 DynamicCastClassException 基本上问题是这样的 T is defined as T NSObject let oebj1 NetworkResponse
  • 使用 Net::SMTP::TLS 时出现“sslv3 警报握手失败”错误

    我正在尝试使用 Perl 发送电子邮件 我的代码在 Yahoo 的 SMTP 服务器上运行良好 但是当我尝试使用另一个 SMTP 服务器 带有自签名 SSL 证书 时 出现以下错误 无法启动 TLS 由于握手问题 SSL 连接尝试失败错误
  • 使用规则禁用 Firebase Cloud Firestore 中的查询集合

    我正在使用 Firebase Cloud Firestore 并且我想修改我的规则以限制用户查询集合 这是不应该允许的 firestore collection users get 但这应该被允许 firestore collection
  • 在函数中使用“use”?

    我正在努力做好以下工作 function flosoftdedicated api init require once resources vendor autoload php use Ovh Common Ovh ovh new Ovh
  • 如何更改xml中所有日期的格式?

    我在 SQL 的单元格中有一个 xml 例如 Table
  • Transact SQL 运行另一个 Transact SQL 脚本

    我有 10 个事务 SQL 脚本 每个脚本都会创建一个表并填充数据 我正在尝试创建 1 个主 sql 脚本来运行其他 10 个脚本中的每一个 有没有办法使用 SQL TRANSACT SQL for Microsoft SQL Server
  • 清洁 Windows Azure 网站

    我的 ASP NET MVC 项目推送到 Azure 网站时带有一个无效的额外 DLL 这导致项目无法正常运行 如果创建了一个新网站 它会完美运行 在本地清理项目并重新部署并不能解决问题 有没有办法执行 远程清洁 该项目是使用发布菜单项直接
  • 无法将电子邮件地址字段放在登录表单上(Authlogic)

    所以我有 Authlogic 可以很好地处理这个user sessions new view Invalid username or password br br br br br br
  • Docker Compose 在启动 Y 之前等待容器 X

    我正在使用rabbitmq和一个简单的python示例here https www rabbitmq com tutorials tutorial one python html与 docker compose 一起使用 我的问题是我需要等
  • Visual Studio 2013 - 如何在控制台中查看输出?

    我是 C 和 VS 的新手 我只是尝试使用 Console WriteLine 打印一行 但它只显示在命令提示符中 有没有办法让输出显示在输出窗口中 编辑 这是一个控制台应用程序 另外 如何访问命令行来运行程序 我只能弄清楚如何使用 F5
  • 在 Symfony2/Twig 中从 2 位国家/地区代码获取翻译后的国家/地区名称?

    我正在使用 Symfony2国家 字段类型 http symfony com doc current reference forms types country html 效果很好 国家名称也被翻译了 我将两位数的国家 地区代码存储在列中c
  • 如何格式化所有其他行以与其之前的行合并? (Python)

    我一直在与 beautiful soup 合作 从网站 API 中提取数据 以便在我正在构建的粉丝网站中使用 我已将数据提取到文本文件中 但在格式化它时遇到问题 Charles Dance Lord Tywin Lannister S 02
  • 如何运行手机版网站?

    运行移动版本网站有两种常见方法 通过服务器端脚本检测移动浏览器以显示移动主题 拥有单独的子域 例如 m domain com 或 mobile domain com 行动上哪个更好 在这两种情况下 我认为移动搜索引擎公平地索引移动网站 每种
  • TSP,算法陷入局部最小值

    我正在努力实现一个基于模拟退火的程序来解决旅行商问题 我得到的所有解决方案都不令人满意 我不知道如何改进我的实施 显然 我不关注基准 而只关注寻找视觉上可接受的最短路径 如果有人能启发我 我将不胜感激 weight function sim
  • Mysql 不使用两列的索引

    我有以下查询 select from my table where col1 col2 in 1000 1 2000 2 我在 col1 col2 以及 col1 和 col2 上定义了索引 如果我对其运行解释 我会发现 mysql 找不到
  • C - 如何使用变量作为 SQL 查询的一部分?

    介绍 我正在尝试使用 C 将变量合并到查询中 我正在使用 sqlite 遵循本教程教程点 https www tutorialspoint com sqlite sqlite c cpp htm 也是我第一次接触使用 SQL 本教程向我展示
  • scala 模式匹配函数 - 如何绕过类型擦除

    我想模式匹配一 个函数 问题是类型擦除 请注意下面的代码片段 尽管warning发出了一场比赛 并且出现了 错误 的比赛 scala gt def f1 gt true f1 gt Boolean scala gt val fl f1 fl