Scala:使用具体类型实现 Map

2024-07-04

我在 Scala 类型系统中遇到了某种怪癖,这让我有点困惑。我正在尝试创建一个扩展 Map[String,String] 的类,但我不太清楚如何以编译器接受的方式实现 + 方法。

这是我现在的代码:

class ParamMap(val pairs:List[(String,String)] = Nil) extends Map[String,String] {

  lazy val keyLookup = Map() ++ pairs

  override def get(key: String): Option[String] = keyLookup.get(key)
  override def iterator: Iterator[(String, String)] = pairs.reverseIterator

  /**
   * Add a key/value pair to the map
   */
  override def + [B1 >: String](kv: (String, B1)) = new ParamMap(kv :: pairs)

  /**
   * Remove all values for the given key from the map
   */
  override def -(key: String): ParamMap  = new ParamMap(pairs.filterNot(_._1 == key))

  /**
   * Remove a specific pair from the map
   */
  def -(kv: (String, String)) : ParamMap = new ParamMap(pairs - kv)
}

Scala 告诉我:

type mismatch;  found: (String, B1)  required: (String, String)

我相信这是因为 B1 被允许成为 String 的子类型,但我的构造函数只需要一个 String (?)。我最初的尝试是:

override def +(kv: (String, String)) = new ParamMap(kv :: pairs)

但这会抱怨,因为类型签名与特征不匹配:

class ParamMap needs to be abstract, since method + in trait Map of type [B1 >: String](kv: (String, B1))scala.collection.immutable.Map[String,B1] is not defined
method + overrides nothing

我是 Scala 的新手,我认为我对类型系统的工作原理感到有些困惑。也许我会尝试搞乱选角,但我有一种感觉,可能会有一种“更好的方法”,如果我知道的话,将来会省去很多麻烦。

有任何想法吗?


有关 Scala 类型系统的一些背景知识。

  • 语法B1 >: String意思是B1 is a 超型 of String. So B1不太具体,并且不能转换为String。反过来,B1 <: String将是一个subtype关系。

  • 的定义Map特质是Map [A, +B], where A代表密钥的类型和B值的类型。这+B符号表示Map is 协变在密钥类型中,这意味着T <: S暗示Map[A, T] <: Map[A, S].

  • 完整类型Map.+方法是+ [B1 >: B] (kv: (A, B1)): Map[A, B1]。协方差为B使用某种力量B1 >: B。这是它如何工作的示例:给定地图m: Map[String, String]添加类型不太具体的键值对kv : (String, Any)将导致地图不太具体,(m + kv): Map[String, Any].

最后一点说明了您的问题ParamMap定义。根据Map接口,应该能够添加类型的键Any到类型的地图ParamMap <: Map[String, String]并得到一个Map[String, Any]。但你试图定义ParamMap.+总是回来ParamMap[String, String],这与Map.+.

解决问题的一种方法是给出ParamMap显式类型参数,类似于(警告未经测试),

class ParamMap[B](val pairs:List[(String,String)] = Nil) extends Map[String, B] {
  ...
  override def + [B1 >: B](kv: (String, B1)) = new ParamMap[B1](kv :: pairs)
}

但这可能不是您想要的。我认为没有办法将值类型修复为String并实施Map[String, String]界面。


鉴于上述所有内容,为什么您答案中的代码可以编译?您实际上已经发现了 Scala 模式匹配的局限性(不健全),它可能导致运行时崩溃。这是一个简化的示例:

def foo [B1 >: String](x: B1): Int = {
  val (s1: Int, s2: Int) = (x, x)
  s1
}

虽然可以编译,但它没有做任何有用的事情。事实上,它总是会崩溃MatchError:

scala> foo("hello")
scala.MatchError: (hello,hello) (of class scala.Tuple2)
    at .foo(<console>:9)
    at .<init>(<console>:10)
    at .<clinit>(<console>)
    ...

在你的回答中,你基本上告诉编译器将B1实例到一个String,如果转换不起作用,您将遇到运行时崩溃。相当于不安全的强制转换,

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

Scala:使用具体类型实现 Map 的相关文章

  • 在 Scala 中修改 XML 而不进行突变?

    我正在尝试替换 XML 片段 并且在此过程中需要一个累加器 假设我有一个填空题存储为 XML 如下所示 val q
  • Doctrine2:类型 x 已经存在

    我对 Doctrine API 有疑问 我想添加一个新的学说类型 我按照本文档创建了该类 并且已在自定义驱动程序中添加了该类型 Type addType custom Namespace NameBundle Types CustomTyp
  • 我什么时候应该使用 Scala 的数组而不是其他集合之一?

    这更多的是风格和偏好的问题 但这里是 我什么时候应该使用 scala Array 我一直使用 List 偶尔会遇到 Seq Map 等 但我从未在野外使用或见过 Array 仅仅是为了兼容 Java 吗 我错过了一个常见的用例吗 首先 我们
  • Java客户端找不到主节点:MasterNotDiscoveredException等待[1m]

    我正在使用 vagrant 并使用 debian 软件包在其上安装了 ES elasticsearch 1 1 1 deb 在我的网络应用程序中 我使用 jar org elasticsearch elasticsearch 1 1 1 我
  • “特征”和“模板特征”有什么区别?

    查看 Traversable 和 TraversableLike 的 scaladoc 我很难弄清楚它们之间的区别 除了一个扩展了另一个 文档中唯一明显的区别是 它说 Traversable 是一种 特征 而 TraversableLike
  • 为什么 SimpleDateFormat 解析错误的日期?

    我有字符串格式的日期 我想将其解析为实用日期 var date 03 11 2013 我将其解析为 new SimpleDateFormat MM dd yyyy parse date 但奇怪的是 如果我通过 03 08 201309 hj
  • 有没有办法将java数据类型输出到控制台?

    我正在尝试调试我继承的程序 该程序包含字符串 数组列表和集合 类型之间的大量转换 并且我需要进行一些字符串操作 substring etc 数据look就像打印到控制台时的字符串一样 例如 它是一行文本 例如Johnson John or
  • 处理 Scala 对象构造函数中的异常

    我正在尝试使用 Lift JPA 当我引用 Model 时 它调用超级构造函数 我遇到了异常 object Model extends LocalEMF LiftPersistenceUnit with RequestVarEM 问题是这个
  • udf 没有可用于字符串类型的 TypeTag

    我不明白火花的行为 我创建一个 udf 它返回一个如下所示的整数 import org apache spark sql SQLContext import org apache spark SparkConf SparkContext o
  • Scala 是一个更好的 println

    我经常发现自己在做这样的事情 println foo 当我想做的时候 println foo 编译器不允许这样做 还有 println很拗口 我真的只想说 echo foo 因此 在基础包对象中 我创建了 println 的 echo 版本
  • 在elastic4s上找不到值索引错误

    我尝试使用以下方法将一些数据索引到弹性搜索弹性4s https github com sksamuel elastic4s API 但我收到编译错误not found value index 这是代码 稍后我会将 js 对象字段映射到弹性搜
  • Scala 转换为变量类型

    我有以下代码要投射value的类型default def fct T value Any default T T val result value asInstanceOf T println result result getClass
  • 是否可以写一个不可变的双向链表?

    我觉得问这个问题有点愚蠢 但我目前正在学习函数式编程并完成了创建单链表的练习 这让我开始思考 是否有可能创建一个不可变的双链表 假设列表 A B 在构造时 A 需要了解 B 但 B 也需要了解 A 我一直在 Scala 中这样做 所以我不确
  • 是否可以写一个不可变的双向链表?

    我觉得问这个问题有点愚蠢 但我目前正在学习函数式编程并完成了创建单链表的练习 这让我开始思考 是否有可能创建一个不可变的双链表 假设列表 A B 在构造时 A 需要了解 B 但 B 也需要了解 A 我一直在 Scala 中这样做 所以我不确
  • 如何强制 F[_] 成为 Monad 的实例

    我有以下类定义 final case class Creator F topic String discovery ServiceDiscovery F implicit sync Sync F import JsonDeserialize
  • 将元素添加到向量末尾

    斯卡拉文档 http www scala lang org api current index html scala collection immutable Vector解释如何向 Vector 添加元素 def elem A Vecto
  • stdatomic (C11),关于 _Atomic 类型的三个问题

    第一个问题 我在 cppreference 上找到了 Atomic type name 自 C11 起 用作类型说明符 这指定了一个新的原子类型 Atomic type name 2 自 C11 起 用作类型限定符 这指定类型名称的原子版本
  • Scala 风格:for 与 foreach、filter、map 等

    scala 中对集合进行 高级迭代 的最佳风格是什么 在什么情况下我应该使用 for compression 什么时候我应该寻找替代的迭代方式 就风格而言 在Programming in Scala书中有一个例子 看起来几乎和下一个一样 f
  • 使用 Scala IDE 自动完成功能时 Eclipse 中出现错误

    使用 Scala IDE 的 Eclipse 中的自动完成 ctrl space 失败 并出现以下错误 An internal error occurred during Computing additional info org ecli
  • 在 Scala 中指定 lambda 返回类型

    注意 这是一个理论问题 我并不是试图解决任何问题 也不是试图达到任何实际效果 在 Scala 中创建 lambda 时使用 arguments gt expression语法 可以显式提供返回类型吗 Lambda 与方法没有什么不同 它们都

随机推荐

  • 读取 NFC 标签时出现奇怪的字符

    我正在尝试使用 Android 读取 NFC 标签 我是一名养蜂人 这是为了在我接近蜂巢时识别它们 我已经在这里搜索过 但阅读标签时仍然遇到问题 我想阅读文本 但是当它阅读时 在所需文本之前有一个类似正方形的字符和显示为 十 的字符 这是我
  • 让 Android 源中的应用程序编译到 system/app 而不是 data/app 中?

    我正在从源代码编译 Android ROM 并且我有几个可以编译的应用程序 但会编译到手机上的数据 应用程序中 它们可以通过手机设置卸载 我希望它们不可能从手机中卸载 并编译到系统 应用程序而不是数据 应用程序中 有什么建议吗 编辑 错别字
  • 为什么我无法初始化 Map? [复制]

    这个问题在这里已经有答案了 我想存储一组int String值 但是ints 不一定是增量的 这意味着数据可以是 lt 1 first gt lt 3 second gt lt 9 third gt 所以我正在尝试创建与Dictionary
  • Gulp Sass - 如何正确命名输出 css?

    我正在阅读有关 sass 的教程here https scotch io tutorials getting started with sass然后我尝试了其他方法 但在本教程中无法得到答案 这就是问题所在 我的 gulpfile js 中
  • 如何仅针对一项特定修改器更改应用动画?

    如何只申请 animation to offset同时保持其他修改器更改不受其影响 添加 animation偏移后也会使字体大小发生变化 Main view var body some View GeometryReader geo in
  • Androidx 模块,android:attr/ttcIndex 和 android:attr/fontVariationSettings 未找到

    我正在将所有支持 appcompat 库迁移到 androidx 所有更新后 由于此错误 我无法构建我的项目 app processDebugManifest UP TO DATE AGPBI kind error text error r
  • 处理 jQuery 中的所有事件类型

    在使用 jQuery 的应用程序中 我希望每次触发任何类型的事件 包括自定义事件 时都记录到控制台 无论如何 是否可以在不修改 jQuery 源代码并且不绑定到每个可能的事件类型的长列表的情况下执行此操作 var oldTrigger jQ
  • pyqt 中的代码编辑器示例

    我尝试学习一些Qt PyQt 为此 我使用了代码编辑器示例 http doc qt io qt 4 8 qt widgets codeeditor example html的文档 当前行的突出显示效果很好 但行号不显示 实际上LineNum
  • 即使授予用户组完全权限后也无法在 C:\ProgramData\ 中创建文件

    我们有一个应用程序尝试写入 C ProgramData 文件夹中的 Access 数据库 mdb 在启用 UAC 的计算机上 我们发现访问数据库失败 因为它似乎无法创建锁定文件 默认情况下 可能是由于 UAC 用户 包括管理员 似乎没有写入
  • Rails 3 Observer——希望学习如何为多个模型实现观察者

    我想添加一个 Auditor Observer 它可以在创建 3 个模型 书籍 人物 作者 后随时执行操作 我最近听说了观察者功能 但找不到任何有关该功能的文档 Rails 3 支持吗 如何创建一个 Auditor Observer 来为
  • R as.POSIXct() 删除小时、分钟和秒

    我正在尝试用 R 来分析一些测量数据 我有一个 csv 文件 其中包含超过 200 万条测量线 这是一个例子 2014 10 22 21 07 03 00 00 7432442 0 2014 10 22 21 07 21 00 00 743
  • 禁用 Android Monkey 上的系统级事件

    当猴子测试我的应用程序时 adb shell monkey p com foo bar throttle 1000 v 14400 我注意到它可以访问我设备上的各种系统设置 例如音频控制和屏幕截图 根据http developer andr
  • 使用 gdb 在 xv6 上调试用户代码

    我正在做一个基于 xv6 的操作系统类 并且编写了一个需要在其上运行的程序 我知道我可以调试内核代码make qemu gdb但我不知道如何调试我自己的用户程序 假设我想调试cat 我该怎么做呢 Thanks 附 不是有xv6标签吗 这个问
  • Gitweb 失败:致命:refs/heads/master 缺少对象 0000000000000000000000000000000000000000 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在尝试将 gitweb 与一组由
  • 错误:“访问受限 URI 被拒绝”

    访问受限 URI 被拒绝 代码 1012 中断此错误 xhttp send null function getXML xml file if window XMLHttpRequest var xhttp new XMLHttpReques
  • 如何使用生产存储桶数据启动 Firebase 存储模拟器?

    我正在使用 Firebase 模拟器来运行所有 Firebase 服务 我已成功通过运行以下命令来运行模拟器并备份 Firestore 数据 firebase emulators start import my directory 但我找不
  • Chart.js 忽略画布高度和宽度

    继Chart js 文档 http www chartjs org docs getting started creating a chart我正在尝试绘制一个小图表
  • 无堆栈协程与堆栈协程有何不同?

    背景 我问这个问题是因为我目前有一个具有许多 数百到数千 线程的应用程序 这些线程中的大多数在很大一部分时间内处于空闲状态 等待将工作项放入队列中 当工作项可用时 它会通过调用一些任意复杂的现有代码来处理 在某些操作系统配置上 应用程序会遇
  • 输入与输出上的 HTML/XSS 转义

    从我所看到的一切来看 对用户输入的内容转义 html 为了防止 XSS 的目的 的惯例似乎是在渲染内容时执行此操作 大多数模板语言似乎默认都会这样做 我遇到过类似的事情这个 stackoverflow 答案 https stackoverf
  • Scala:使用具体类型实现 Map

    我在 Scala 类型系统中遇到了某种怪癖 这让我有点困惑 我正在尝试创建一个扩展 Map String String 的类 但我不太清楚如何以编译器接受的方式实现 方法 这是我现在的代码 class ParamMap val pairs