gpt4 book ai didi

Scala:使用依赖注入(inject)协调类型类

转载 作者:行者123 更新时间:2023-12-03 13:59:51 25 4
gpt4 key购买 nike

最近 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)

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

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

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

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

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

人们会建议 Scala 的哪些技术和依赖注入(inject)库来解决这个问题?我错过了一个技巧吗?完美的 DI 库?或者这真的是它看起来的症结所在?

澄清

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

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

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

最佳答案

可以通过使用新的上下文绑定(bind)语法来减轻传递这些隐式依赖项的相当数量的乏味。你的例子变成

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

它的编译方式相同,但签名清晰明了,并且 float 的“噪声”变量更少。

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

关于Scala:使用依赖注入(inject)协调类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3255991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com