Scala 中的类型类解析如何工作?

2024-05-08

我有一个带有类型参数的函数,我想知道该类型参数是否是一个Option或不。我读过一些博文,即this one http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html最近关于scala中的类型类,所以我想出了这个解决方案:

case class OptionFinder[A](isOption: Boolean)
implicit def notOption[A]: OptionFinder[A] = OptionFinder(false)
implicit def hitOption[A]: OptionFinder[Option[A]] = OptionFinder(true)

def myFunction[A](value: A)(implicit optionFinder: OptionFinder[A]): String = {
    if (optionFinder.isOption) {"Found Option!"} else {"Found something else."}
}

这似乎按预期工作:

scala> val x: Option[Int] = Some(3)
scala> myFunction(x)
res0: String = Found Option!

scala> val y: String = "abc"
scala> myFunction(y)
res1: String = Found something else.

如果是Some(3) hitOption是隐式参数,即使notOption也会匹配(与A = Option[Int])。显然,更具体的是选择的类型。但我能保证编译器总是选择更具体的类型吗?那么它在编译器中是如何工作的呢?我还没有找到这种行为的文档。

注意:也许这个问题的标题不是最好的,我很乐意将其更改为更好的标题。


已经有一个关于此的问题:Scala:隐式参数解析优先级 https://stackoverflow.com/questions/8623055/scala-implicit-parameter-resolution-precedence。它通过一个复杂的过程来回答自己博客文章 http://eed3si9n.com/revisiting-implicits-without-import-tax。我认为最重要的信息是 Martin Odersky 对博客文章的评论:

这是隐式搜索的更高级解释 在 Scala 中,这对应于规范的解释方式,但是在 稍微不那么形式主义的语言。

  1. 首先,我们寻找作为局部变量或作为封闭类和包的成员或作为导入可见的隐式变量 - 精确的规则是我们应该能够使用他们的名字来访问它们 仅,没有任何前缀。

  2. 如果在步骤 1 中没有找到隐式对象,我们将查看“隐式作用域”,其中包含带有某些功能的所有伴生对象。 与我们搜索的类型的关系(即 类型本身、其参数(如果有)以及其参数 超类型和超特质;重要性在于一般化 无需像 Haskell 一样进行整个程序分析 做)。

如果在任一阶段我们发现多个隐含的消歧 开始。消歧与重载完全相同 解决。静态重载解析解析规则有点 涉及到,这里就不重复了。如果有什么安慰的话: Java 的规则和 C# 的规则比 Scala 的规则复杂得多 在这个区域。

现在根据这个解释,它是“静态重载解析规则”,它将消除之间的歧义notOption and hitOption。老实说,我不明白如何做到。

这个答案 https://stackoverflow.com/a/1887678/1374461解释说确实具有更具体参数的方法具有优先级,但我不知道这是否或如何与重载规则相关。

如果我是你,我不会太依赖这种行为,而是通过继承使用更容易理解的隐式优先级概念。无论如何,将隐含内容放入伴生对象中是个好主意。

归根结底,继承的隐式优先级较低。因此,可以安全地将隐含的内容退回到 ifhitOption与伴生对象扩展的特征不匹配。

case class OptionFinder[A](isOption: Boolean)

object OptionFinder extends LowerPriority {
  implicit def hitOption[A]: OptionFinder[Option[A]] = OptionFinder(true)
}

trait LowerPriority {
  implicit def notOption[A]: OptionFinder[A] = OptionFinder(false)
}

def myFunction[A](value: A)(implicit optionFinder: OptionFinder[A]): String = {
    if (optionFinder.isOption) {"Found Option!"} else {"Found something else."}
}

如果您将隐式对象放在非伴生对象中,这也应该有效MyImplicits并导入它们import MyImplicits._.

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

Scala 中的类型类解析如何工作? 的相关文章

  • 引用Scala中内部类的类型

    下面的代码尝试模仿DSL 的多态嵌入 http www daimi au dk ko papers gpce50 hofer pdf 而不是给出行为Inner 它被编码在useInner其封闭类的方法 我添加了enclosing方法 以便用
  • 强制类型差异

    在 Scala 中 我可以在编译时强制执行类型相等 例如 case class Foo A B a A b B implicit ev A B scala gt Foo 1 2 res3 Foo Int Int Foo 1 2 scala
  • 如何将 csv 文件读取为键值对的映射

    我的 csv 文件中有数据 例如 value key A Name B Name C Name 24 Age 25 Age 20 Age M Gender F Gender 我想解析它以生成以下地图 Map Name gt List A B
  • Scala:var List 与 val MutableList

    在 Odersky 等人的 Scala 书中 他们说使用列表 我还没有从头到尾读过这本书 但所有的例子似乎都使用了 val List 据我了解 还鼓励人们使用 vals 而不是 vars 但在大多数应用程序中 使用 var List 或 v
  • Scala 中的超时未来

    假设我有一个函数 它调用一个阻塞可中断的手术 我想在超时的情况下异步运行它 也就是说 我想在超时到期时中断该功能 所以我正在尝试做这样的事情 import scala util Try import scala concurrent Fut
  • 如何从 lift webapp 读取文件

    我想在我的 lift 应用程序中读取 xml 文件 val data XML load new java io InputStreamReader new java io FileInputStream 文件名 编码 然而 我得到java
  • Scala SBT 版本依赖性二进制兼容性错误 scala-xml

    我有一个在 GitHub 上托管的项目 我使用 scala steward 来保持我的插件和依赖项最新 这在一段时间内有效 但现在使用此类自动更新却变成了一场噩梦 事情是这样的 在我的plugins sbt中 我依赖于scoverage 它
  • 对列表中的相邻元素进行分组

    假设我想编写一个函数来执行此操作 输入 1 1 3 3 4 2 2 5 6 6 输出 1 1 3 3 4 2 2 5 6 6 它将相同的相邻元素分组 这个方法的名称应该是什么 此操作有标准名称吗 In 1 1 3 3 4 2 2 5 6 6
  • Akka/Scala:映射 Future 与 pipelineTo

    In Akka参与者 在发送一个Future结果给另一个演员 A 映射Future发挥作用tell结果给演员 B 定义一个onSuccess未来的回调 其中tell结果给演员 C 管道Future结果给演员pipeTo 其中一些选项已在上一
  • 具有动态命名参数的 Scala 案例类副本

    对于具有参数数量的 scala 案例类 21 e g case class Car type String brand String door Int 其中类型 吉普车 品牌 丰田 门 4 etc 还有一个复制方法允许使用命名参数覆盖 Ca
  • 从会话中读取数据时如何发出加特林捕获请求?

    根据加特林文档 http gatling io docs 2 1 7 session session api html 我可以在执行场景时使用会话属性 但是 每次我在场景中使用函数文字访问会话时 都会遇到以下异常 error java la
  • 在 scala 中保留推导的更高类型

    我有一个高阶类型 并致力于用它构建一些 DSL 我正在寻找一种方法来定义可以接受类型而无需显式指定此类型的函数 自我描述示例 class Wrap T val data T class DSL def doSomething T x Wra
  • Scala:需要类类型,但找到了 T

    我发现了与此特定问题类似的问题 但是该问题是由于有人试图直接实例化 T 造成的 在这里 我试图创建一个特征 它是一个通用接口来扩展类并将它们自动存储在数据库中 例如 Riak 使用classOf T 使用 Scala 2 10 这是我的代码
  • 手动排除sbt中的一些测试类

    我通常在 CI 中执行以下命令 清理更新编译测试发布 但是 我想从 sbt 命令行中排除 1 个 或几个 测试类 我怎样才能做到这一点 我不想更改我的代码以使用忽略等 两种可能的选择 test only See http www scala
  • 为什么 Cassandra 客户端在生产中没有 epoll 时会失败? [复制]

    这个问题在这里已经有答案了 当我在本地运行服务时 我收到一条警告 指出 epoll 不可用 因此它使用 NIO 很公平 当我将其部署到 Kubernetes 中时 我得到了以下信息 这导致服务无法运行 2017 03 29T19 09 22
  • 在 Spark 中将流式 XML 转换为 JSON

    我是 Spark 新手 正在开发一个简单的应用程序 将从 Kafka 接收的 XML 流转换为 JSON 格式 Using 火花2 4 5 斯卡拉 2 11 12 在我的用例中 kafka 流采用 xml 格式 以下是我尝试过的代码 val
  • Scala 条件列表构造

    我正在使用 Scala 2 9 2 并且想根据某些条件构建一个列表 考虑以下情况 其中 cond 是采用谓词 p 和类型 T 的值 在本例中为 t3 的某个函数 t1 t2 cond p t3 t4 我想要的行为如下 如果 p 为真 则应给
  • 带可变参数的 Spark UDF

    如文档中所示 列出最多 22 个参数是唯一的选择吗 https spark apache org docs 1 5 0 api scala index html org apache spark sql UDFRegistration ht
  • Scala 警告、IntelliJ 和编译器标志

    我目前正在试用 IntelliJ Scala 插件 有件事让我有点烦恼 编译时我收到 3 个警告 Warning scala Recompiling 4 files Warning scala Warning scala there wer
  • akka-http:找不到参数解组的隐式值

    我的 Spray json 支持看起来像这样 object MarshallingSupport extends SprayJsonSupport implicit def json4sFormats Formats DefaultForm

随机推荐