为什么会发生这种隐含的歧义行为?

2024-03-05

我有一个类型类Search,其中有一个实例Search[A]如果我们有一个TypeClass1[A] or a TypeClass2[A]实例。优先考虑1实例。

编译如下:

trait TypeClass1[A]
trait TypeClass2[A]
trait Search[A]

object Search extends LPSearch {
  implicit def case1[A](implicit ev: TypeClass1[A]): Search[A] = null
}

trait LPSearch {
  implicit def case2[A](implicit ev: TypeClass2[A]): Search[A] = null
}

object Test {
  implicit val ev1: TypeClass1[Int] = null
  implicit val ev2: TypeClass2[Int] = null
  implicitly[Search[Int]]
}

这正如我所期望的,隐式搜索发现case1, finds ev1,并停止搜索。

然而,如果我们改变TypeClass2为了获得更多结构,隐式搜索停止工作:

trait TypeClass1[A]
trait TypeClass2[M[_], A]
trait Search[A]

object Search extends LPSearch {
  // This is the same as before
  implicit def case1[A](implicit ev: TypeClass1[A]): Search[A] = null
}

trait LPSearch {
  implicit def case2[M[_], A](implicit ev: TypeClass2[M, A]): Search[M[A]] = null
}

object Test {
  implicit val ev1: TypeClass1[List[Int]] = null
  implicit val ev2: TypeClass2[List, Int] = null

  // Does not compile:
  implicitly[Search[List[Int]]]
}

为什么上面的例子中最后一行不能编译?

它失败了ambiguous implicit values,说两者case1 and case2满足条件。

在 scala 2.12.8 和 2.13.0 上观察到的行为


Scala 规范说:

如果有多个符合隐式参数类型的参数,则将使用静态重载解析规则选择最具体的一个。

https://www.scala-lang.org/files/archive/spec/2.13/07-implicits.html#implicit-parameters https://www.scala-lang.org/files/archive/spec/2.13/07-implicits.html#implicit-parameters

替代方案的相对权重A超过替代方案B是一个从 0 到 2 的数字,定义为

  • 1 if A具体如下B,否则为 0,并且
  • 1 if A是在类或对象中定义的,该类或对象派生自定义的类或对象B, 否则为 0。

https://www.scala-lang.org/files/archive/spec/2.13/06-expressions.html#overloading-resolution https://www.scala-lang.org/files/archive/spec/2.13/06-expressions.html#overloading-resolution

  • case1被定义在一个对象中,该对象是derived从类(特质)定义case2但反之则不然。

  • case2 is 具体如 case1但反之则不然。

So 相对重量 of case1 over case21+0=1 且相对重量 of case2 over case1是0+1=1。所以这就是歧义。

Error: ambiguous implicit values:
 both method case2 in trait LPSearch of type [M[_], A](implicit ev: App.TypeClass2[M,A])App.Search[M[A]]
 and method case1 in object Search of type [A](implicit ev: App.TypeClass1[A])App.Search[A]
 match expected type App.Search[List[Int]]
    implicitly[Search[List[Int]]]

在第二种情况下,使用低优先级特征是没有意义的,因为如果两个隐式都匹配预期类型,case2当它们被定义在同一个对象中时是首选。所以尝试一下

object Search {
  implicit def case1[A](implicit ev: TypeClass1[A]): Search[A] = null
  implicit def case2[M[_], A](implicit ev: TypeClass2[M, A]): Search[M[A]] = null
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么会发生这种隐含的歧义行为? 的相关文章

  • Either 相当于受检查的异常吗?

    从 Scala 开始并阅读有关Either我很自然地将新概念与我所知道的东西 在本例中来自 Java 进行比较 与之前有什么区别吗concept检查异常和Either 在这两种情况下 失败的可能性在方法中明确注释 throws或返回Eith
  • Scala 重载构造函数和 super

    我无法理解如何在 Java 上开发类似于以下的 Scala 代码 public abstract class A protected A protected A int a public abstract class B protected
  • Play框架2:如何在路由、视图和控制器之间传递对象?

    我正在尝试将书籍对象从视图传递到路线 然后将其发送到控制器中进行计算 我的代码如下 bookList scala html books java lang Iterable Book main BookList div class row
  • 将列表拆分为多个具有固定元素数量的列表

    如何将元素列表拆分为最多包含 N 个项目的列表 例如 给定一个包含 7 个元素的列表 创建 4 个组 最后一组可能包含较少的元素 split List 1 2 3 4 5 6 seven 4 gt List List 1 2 3 4 Lis
  • Scala:在运行时获取 mixin 接口

    我需要在运行时从给定的类获取所有接口 全部加载在类加载器中 例如 如果一个类是这样声明的 trait B trait C trait D class A extends B with C with D 我想在运行时获取这些信息 A 取决于
  • 了解如何使用 apply 和 unappy

    我试图更好地理解 的正确用法apply and unapply方法 考虑到我们想要序列化和反序列化的对象 这是正确的用法吗 即斯卡拉方式 的使用apply and unapply case class Foo object Foo appl
  • 哪些 ORM 与 Scala 配合得很好? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 自定义 NIO 文件系统无法通过 SBT 的测试任务加载

    为了进行测试 我使用内存中的 NIOFileSystem执行 memoryfs https github com openCage memoryfs 我以前已经利用过它 并且它似乎运行良好 例如梅文 然而 现在 在SBT项目中 不可能初始化
  • 重塑案例类构造函数?

    试图找到一种方法来 重塑 案例构造函数以填充某些默认值 以下情况可能吗 def reshape T R1 lt HList R2 lt HList h R1 R2 gt T example case class MyClass a Doub
  • Scala:具有复杂结构的树插入尾递归

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

    考虑以下类型结构 trait HasId T def id T case class Entity id Long extends HasId Long 比方说 我们想在一些测试中模拟实体类 val entityMock mock Enti
  • Scala:类似 Option (Some, None) 但具有三种状态:Some、None、Unknown

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

    例如如果调用 JavaThread sleep这会抛出一个已检查的InterruptedException来自 Scala 源文件 然后不需要将调用包含在 Scala 中try catch Scala 如何删除将调用包围在 a 中的规则tr
  • Java 表达式树 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有相当于 net的 LINQ 下的表达式树JVM 我想实现一些类似 LINQ 的代码结构Scala
  • Play Framework 2.3 (Scala) 中的自定义 JSON 验证约束

    我设法使用自定义约束实现表单验证 但现在我想对 JSON 数据执行相同的操作 如何将自定义验证规则应用于 JSON 解析器 示例 客户端的 POST 请求包含用户名 username 我不仅要确保该参数是非空文本 而且还要确保该用户确实存在
  • 缓存 Slick DBIO 操作

    我正在尝试加快 SELECT FROM WHERE name 的速度Play 中的查询类型 Scala 应用程序 我正在使用 Play 2 4 Scala 2 11 play slick 1 1 1 包 该软件包使用Slick 3 1版本
  • 类型级编程有哪些示例? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我不明白 类型级编程 是什么意思 也无法使用Google找到合适的解释 有人可以提供一个演示类型级编程的示例吗 范式的解释和 或定义将
  • 使用 scala 在 Flink 中进行实时流预测

    弗林克版本 1 2 0斯卡拉版本 2 11 8 我想使用 DataStream 来使用 scala 中的 flink 模型进行预测 我在使用 scala 的 flink 中有一个 DataStream String 其中包含来自 kafka
  • Scala 解析器组合器的运算符优先级

    我正在研究需要考虑运算符优先级的解析逻辑 我的需求并不太复杂 首先 我需要乘法和除法比加法和减法具有更高的优先级 例如 1 2 3 应视为 1 2 3 这是一个简单的例子 但你明白了 我需要将更多自定义标记添加到优先级逻辑中 我可以根据此处
  • 分析 sbt 构建

    我的 sbt 构建需要很长时间 它又大又复杂 很难知道从哪里开始清理 看起来 sbt 保留了很多关于构建结构的元数据 包括相互依赖关系 命名任务 范围界定等 有了所有这些元数据 似乎很容易跳入并测量每个不同任务 及其范围 花费的时间 在代码

随机推荐