如何在编译时强制执行非泛型类型

2023-12-24

考虑一个通用函数:

def genericFn[T](fn: T => Boolean): Unit = {
  // do something involves T
}

是否可以限制T(在编译时)是一个简单类型,而不是类似的类型List[Int]?


我想解决的底层问题是这样的:

var actorReceive: Receive = PartialFunction.empty
def addCase[T](handler: T => Boolean): Unit = {
    actorReceive = actorReceive orElse ({
        case msg: T => // call handle at some point, plus some other logic
            handler(msg)
    })
}

the addCase函数会导致类型擦除警告,这可以通过要求来解决ClassTag like: def addCase[T: ClassTag](..., but ClassTag仍然无法防范这样的电话:

addCase[List[Int]](_ => {println("Int"); true})
addCase[List[String]](_ => {println("String"); false})

actorReceive(List("str"))    // will print "Int"

上面的代码将打印"Int"虽然根本没有发出任何警告或错误,但有什么办法吗?


如果没有反射,就无法在类型系统中按原样强制执行此操作。

最好的方法是拥有一个类型类,例如NonEraseable[A],这提供了类型没有会在运行时被删除的类型参数的证据。隐含的NonEraseable[A]在范围内应该意味着A没有类型参数。由于手动创建这些内容会很乏味,因此隐式宏可以完成这项工作:

import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context

trait NonEraseable[A]

object NonEraseable {

    implicit def ev[A]: NonEraseable[A] = macro evImpl[A]

    def evImpl[A](c: Context)(implicit tt: c.WeakTypeTag[A]): c.Expr[NonEraseable[A]] = {
        import c.universe._
        val tpe = weakTypeOf[A]
        if(tpe.dealias.typeArgs.isEmpty)
            c.Expr[NonEraseable[A]](q"new NonEraseable[$tpe] {}")
        else
            c.abort(c.enclosingPosition, s"$tpe contains parameters that will be erased at runtime.")
    }

}

使用案例:

def onlySimple[A : NonEraseable](value: A): Unit = println(value)

scala> onlySimple(1)
1

scala> onlySimple(List(1, 2, 3))
<console>:13: error: List[Int] contains parameters that will be erased at runtime.
       onlySimple(List(1, 2, 3))
                 ^

使用这个,你可以强制执行在编译时一个类型参数A与上下文绑定NonEraseable是您想要的类型。 (假设您没有作弊并手动创建类型类的实例)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在编译时强制执行非泛型类型 的相关文章

随机推荐

  • VSCode 中的 .ejs 格式

    这是我的问题 它不可读 为了使 ejs 正常工作 我到目前为止添加了以下内容 我还有保存格式和更漂亮的格式 我正在寻找更好的格式的建议 以便我可以阅读它 files associations ejs html css postcss emm
  • 如何将 PreMake/CMake 集成到 C++ 构建工作流程中

    我目前正在研究 PreMake CMake 但是 我不明白如何在整个跨平台构建工作流程中使用它 事实上 它生成 makefile 或解决方案 那么 如何在每个目标平台上实际构建这些解决方案 您是否必须为每个目标维护一个构建脚本 例如 sh
  • 如何检查当前日期是否在java中两个重复出现的日期之间? [复制]

    这个问题在这里已经有答案了 我正在尝试创建一个应用程序 但在计算今天是否在学年中陷入困境 用户输入两个日期 没有年份 每年都会重复发生 这些是学年的开始和结束日期 我想检查当前日期是否在这两个日期之间 即使它重叠两年 因此 如果学校从 11
  • 推送通知到达时应用程序徽章图标未更新

    我看过关于的问题在午夜更新应用程序徽章 并提供以下选项 应用程序未启动或在后台 徽章数量可能会减少 https stackoverflow com questions 4846787 updating application badge a
  • 用户登录后访问登录页面如何重定向到首页?

    这是我的春季安全配置
  • 将事件函数绑定到类,但使用removeEventListener并删除引用,从而使垃圾收集器能够正常工作

    众所周知 当我们在 JavaScript 中创建类时 普通函数会返回类对象 但事件会返回事件对象 并且类对象会丢失 function class a this name a document addEventListener click t
  • 如何在 bash 中编写看门狗守护进程?

    我想要一种在 shell 脚本中编写守护进程的方法 该守护进程循环运行另一个应用程序 如果它死了则重新启动它 运行时使用 myscript sh从 SSH 会话中 它将启动守护程序的新实例 除非守护程序已在运行 当 SSH 会话结束时 守护
  • Shared_ptr 的隐式转换

    我有 U 类和 T 类的两个共享指针 其中 T 是 U 的基数 进行隐式转换是没有问题的shared ptr u to shared ptr u
  • 如何在 Jetpack Compose 中从 URL 加载图像? [复制]

    这个问题在这里已经有答案了 嗯 我正在研究 Compose UI 而且我只专注于基本的事情 其中之一是使用 Glide 显示来自 URL 的图像 我已尝试以下代码 但未调用委托 onResourceReady 和 onLoadCleared
  • 访问 servlet 实例

    虽然我真的无法想到这种情况的实际用例 但我纯粹希望这是一个好奇心驱动的问题 我知道 servlet 容器保存着 servlet 创建的所有实例 并将请求线程委托给这些实例 对这些实例进行管理也是有意义的 以避免在容器权限之外进行无根据的调用
  • 有没有办法在线程创建/销毁时调用库线程本地初始化/清理?

    这个问题类似于如何在线程创建和退出时调用函数 https stackoverflow com questions 42229612 how to call a function on a threads creation and exit但
  • iPhone 版本的“显示包内容”显示空白 PNG?

    所以我成功地完成了我的第一个 iPhone 版本构建 当我好奇地转到新鲜出炉的 app 文件的 显示包内容 时 我注意到所有包含的 PNG 都是空白的 它们都设置为适当的分辨率 但是当我打开它们时 除了默认的 Preview app 灰色之
  • 如何在 Ruby 中找到字符串的第一个非重复字母?

    我有一根绳子 teststring 我想在 Ruby 中找到第一个非重复字符 我有这个Python代码 def first non repeat character teststring unique repeated for charac
  • Flask-登录不重定向到上一页

    我看到了很多与此相关的问题 但无法解决我的问题 我有一个 Flask 应用程序 带有 Flask login 用于会话管理 而且 当我尝试在不登录的情况下查看页面时 我会被重定向到以下形式的链接 login next 2Fsettings
  • 手动将元素添加到 d3 中的选择中

    我正在尝试以编程方式在 d3 中创建一个表 其顶部有四分之一 左侧有值 给定一个四分之一向量 q1 q2 q3 q4 我想要表格 q1 q2 q3 q4 v1 v2 运行下面的代码时我得到的是 q2 q3 q4 v1 v2 请注意 第一列缺
  • DriveApp.GetFoldersByName() 始终返回 true

    我一直在玩谷歌驱动器脚本 我需要从电子表格创建一个文件夹 以防具有该名称的文件夹不存在 但问题是 它说该文件夹存在 即使它不存在 支票位于try功能 像这样 try currentName is the name of the folder
  • 如何获取具有系统托盘图标的进程

    我正在尝试创建获取具有系统托盘图标的进程列表的应用程序 我进行了大量搜索并找到了一些参考资料 http www raymond cc blog find out what program are running at windows sys
  • AVAudioPlayer 不播放文件夹内的歌曲?

    我使用此代码来播放歌曲 但它不播放除文档目录之外的文件夹或文件夹中的歌曲 NSString songname NSString stringWithFormat songArray songIndex NSLog songname song
  • Flexbox justify-content 无法与变换比例正常工作

    我有一个常规的无序列表项目display flex and justify content space between应用于它 结果 first item触及左边缘 list and last item触及右边缘 list ul class
  • 如何在编译时强制执行非泛型类型

    考虑一个通用函数 def genericFn T fn T gt Boolean Unit do something involves T 是否可以限制T 在编译时 是一个简单类型 而不是类似的类型List Int 我想解决的底层问题是这样