Scala:通过依赖注入协调类型类

2024-02-06

最近,Scala 博主们似乎对类型类模式,其中一个简单的类具有由符合某些特征或模式的附加类添加的功能。作为一个过于简单化的例子,简单的类:

case class Wotsit (value: Int)

可以适应 Foo 特征:

trait Foo[T] {
  def write (t: T): Unit
}

在此类的帮助下:

implicit object WotsitIsFoo extends Foo[Wotsit] {
  def write (wotsit: Wotsit) = println(wotsit.value)
}

类型类通常在编译时通过隐式捕获,允许将 Wotsit 及其类型类一起传递到高阶函数中:

def writeAll[T] (items: List[T])(implicit tc: Foo[T]) =
  items.foreach(w => tc.write(w))

writeAll(wotsits)

(在你纠正我之前,我说过这是一个过于简单的例子)

However,隐式的使用假定在编译时已知项的精确类型。我发现在我的代码中通常情况并非如此:我将拥有某种类型的项目 List[T] 的列表,并且需要发现正确的类型类来处理它们。

Scala 建议的方法似乎是在调用层次结构中的所有点添加 typeclass 参数。当代码扩展时,这可能会变得烦人,并且这些依赖项需要通过它们越来越不相关的方法沿着越来越长的链传递。这使得代码变得混乱且难以维护,这与 Scala 的初衷相反。

通常,这是依赖注入介入的地方,使用库在需要时提供所需的对象。详细信息因为 DI 选择的库而异 - 我过去用 Java 编写了自己的库 - 但通常注入点需要精确定义所需的对象。

问题是,对于类型类,精确值在编译时是未知的。必须根据多态性描述来选择它。至关重要的是,类型信息已被编译器删除。清单是 Scala 的类型擦除解决方案,但我还不清楚如何使用它们来解决这个问题。

人们会建议使用哪些 Scala 技术和依赖注入库来解决这个问题?我错过了一个技巧吗?完美的 DI 库?或者这确实是症结所在?


澄清

我认为这实际上有两个方面。在第一种情况下,需要类型类的点是通过从已知其操作数的确切类型的点进行直接函数调用来到达的,因此足够的类型争论和语法糖可以允许将类型类传递给点它是需要的。

在第二种情况下,这两点被屏障分开 - 例如无法更改的 API,或存储在数据库或对象存储中,或序列化并发送到另一台计算机 - 这意味着类型类可以' t 与其操作数一起传递。在这种情况下,给定一个其类型和值仅在运行时已知的对象,需要以某种方式发现类型类。

我认为函数式程序员习惯于假设第一种情况——使用足够高级的语言,操作数的类型总是可知的。 David 和 mkniessl 对此提供了很好的答案,我当然不想批评这些。但第二种情况确实存在,这就是为什么我将依赖注入引入到问题中。


通过使用新的上下文绑定语法,可以减轻传递这些隐式依赖项的大量繁琐工作。你的例子变成

def writeAll[T:Foo] (items: List[T]) =
  items.foreach(w => implicitly[Foo[T]].write(w))

它的编译方式相同,但可以产生漂亮而清晰的签名,并且周围有更少的“噪音”变量。

这不是一个很好的答案,但替代方案可能涉及反射,而且我不知道有任何库可以使其自动工作。

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

Scala:通过依赖注入协调类型类 的相关文章

随机推荐

  • .NET Windows 窗体应用程序是否可以在 64 位操作系统中运行,或者是否需要修改?

    一般来说 NET Windows 窗体应用程序可以在 64 位操作系统中运行吗 还是需要修改 如果它不依赖于 32 位外部库 例如 COM 组件 它将作为 64 位进程完美工作 并利用其优势 大地址空间 x64 指令集 如果它依赖于 32
  • xaml.cs 中的 Xamarin 局部变量并通过 XAML 文件进行打印

    我希望能够打印 XAML 中 CurrentOrder 的属性 这是我到目前为止所拥有的 OrderPage xaml cs public partial class OrderPage ContentPage private Order
  • 使用 MediatR 时可以让一个处理程序调用另一个处理程序吗?

    或者这被认为是不好的做法还是什么 我有一个通知触发 4 5 个处理程序 这些处理程序依次调用数据库来检索数据 每个这些调用也可以单独调用 因此它们本身就是请求 处理程序 Thanks Jimmy Bogard mediatr 的作者 说你应
  • CListCtrl 用鼠标选择多行

    There is a CListCtrl with SetExtendedStyle LVS EX GRIDLINES LVS EX FULLROWSELECT a single selection is false I want to b
  • 如何使用Windows Media Player播放加密的视频文件?

    我加密我的 mp4转换为自定义格式 opu 现在我应该解密我的文件并将它们保存到应用程序开始时的临时文件夹中 并使用它们来播放WindowsMediaPlayerC 中的控制 所以我有从临时文件夹中窃取文件的风险 防止我的文件被盗的最佳方法
  • 从亚马逊s3存储桶检索静态文件

    我正在尝试以这样的方式配置我的 nginx 每当出现一些错误的网关响应时 我都会尝试从 s3 存储桶中获取静态 html 内容 请求的url结构为some bucket folder1 folder2 text 数据存储在 s3 存储桶中
  • 如何设置编辑器以在 Windows 上使用 Git?

    我正在尝试Windows 上的 Git 我尝试 git commit 并收到此错误 终端很笨 但没有 VISUAL 也没有 编辑器定义 请提供 使用 m 或 F 选项的消息 所以我发现我需要一个名为 EDITOR 的环境变量 没问题 我将其
  • 单元测试 Maven 插件

    我正在寻找有关如何为 Maven 插件编写单元测试的信息 虽然有a page http maven apache org plugin developers plugin testing html在关于这一主题的 Maven 站点上 只有一
  • 不可哈希类型:“dict”类型错误[重复]

    这个问题在这里已经有答案了 假设我有这本字典 items 1 title u testing123 description u testing456 2 description u testing123 description u test
  • IPython 中的物理括号符号

    我正在努力拥有ket符号通常在乳胶中写为 ket psi 然而 当写在 当使用以下方式编写时 这也不起作用IPython display latex documentclass article usepackage amsmath begi
  • AngularJS - 将多个 get 请求收集到 json 数组中,然后传递给指令

    我是角度新手 一直在努力解决我的问题 我需要多次访问 API 来获取用户数据 将所有内容存储为 JSON 数组 当收集所有数据 所有结果作为一个数组 时 需要将其传递给指令 该指令将使用它来绘制可视化 例如 d3 js 饼形图 scope
  • ctx.Err() 与 ctx.Done() chan 关闭检查:有区别吗?

    我处于一个长时间运行的可取消函数中 该函数具有永远循环 我需要检查上下文是否已关闭 go func for if ctx Err nil return do work vs go func for select case lt ctx Do
  • Xcode 组织者尝试在错误的目录路径访问传输程序

    Transporter not found at path usr local itms bin iTMSTransporter You should reinstall the application 所以我检查了路径 Applicati
  • java 具有透明度的全屏窗口

    我正在尝试使用 Java 创建一个覆盖整个屏幕的全屏窗口 这个窗口还必须有一定的透明度 大约30 50 透明 当我说整个屏幕时 我的意思是它覆盖了所有内容 包括 OSX Linux Windows 中的扩展坞 任务栏 菜单栏 当我说透明度时
  • Autofac - 将属性注入 asp.net mvc 控制器

    我有一个基本控制器 它继承了我的所有控制器 这个基本控制器有一些属性 我想使用属性注入来注入 我的控制器注册看起来像这样 builder RegisterControllers Assembly GetExecutingAssembly 我
  • 在 ListView 布局模板中显示总计

    我使用 ListView 控件 ASP NET 2008 来显示一堆数据行 在底部我想要一些总计 我最初打算在 LayoutTemplate 中定义页眉和页脚 并使用一些本地函数 即 获取总计 但 LayoutTemplate 似乎不处理
  • 如何使用 java Firebase Admin SDK 将分析标签添加到数据消息?

    自 7 月 1 日起 Firebase 要求向消息添加标签 以便分析显示数据消息发送的数量等 从 2019 年 7 月 1 日星期一开始 您将能够通过分析标签过滤数据 在该日期之后 没有分析标签发送的数据消息可能不会在此仪表板中显示 问题是
  • 连续检查队列

    我想要一个函数来在一个线程上连续检查队列是否有新添加 显然 可以选择连续循环睡眠 但我想要一些不那么浪费的东西 我考虑了某种类型的等待句柄 然后让队列向它发出信号 但我无法安全地覆盖 Enqueue 因为它不是虚拟的 现在我正在考虑封装一个
  • 奇怪的重复出现的模板和模板参数相关的子类化问题

    我正在尝试使以下代码工作 template lt class derived class object typename derived Object gt struct Base using Derived derived using O
  • Scala:通过依赖注入协调类型类

    最近 Scala 博主们似乎对类型类模式 其中一个简单的类具有由符合某些特征或模式的附加类添加的功能 作为一个过于简单化的例子 简单的类 case class Wotsit value Int 可以适应 Foo 特征 trait Foo T