Scala:使用依赖注入协调类型类
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的建议方法似乎是在调用层次结构中的所有点添加类型参数。这可能会使代码范围变得烦人,这些依赖关系需要通过越来越多的不相关的方法传递给越来越长的链。这使得代码凌乱而难以维护,与Scala相反。 通常,这是依赖注入将进入的地方,使用库在需要的时候提供所需的对象。详细资料因为DI选择的图书而有所不同 – 我以前在Java中编写了自己的图书,但通常注入点需要精确定义所需的对象。 在类型类的情况下,编译时不知道精确的值。必须根据多态描述进行选择。关键是,类型信息已被编译器擦除。清单是Scala的类型擦除的解决方案,但是对于我来说,如何使用它们来解决这个问题是非常明显的。 人们建议什么技术和依赖注入库来解决这个问题?我错过了一个技巧吗?完美的DI图书馆?或者这真的是粘贴点吗? 澄清 我认为这真的有两个方面。在第一种情况下,需要类型类的点是通过直接函数调用从操作数的确切类型已知的地方获得的,因此足够的类型争吵和句法糖可以允许类型类被传递到指出它是必需的。 在第二种情况下,两个点由一个屏障分隔开,例如不能更改的API,或存储在数据库或对象存储中,或序列化并发送到另一台计算机 – 这意味着类型类可以“与其操作数一起传递。在这种情况下,给定一个类型和值只在运行时才知道的对象,类型类需要以某种方式被发现。 我认为功能性程序员有习惯假设第一种情况 – 用足够先进的语言,操作数的类型将永远是可以知道的。 David和mkniessl为此提供了很好的答案,我当然不想批评那些。但第二种情况肯定存在,这就是为什么我将依赖注入带入问题的原因。 解决方法
通过使用新的上下文绑定语法,可以减轻相当多的传递这些隐式依赖关系的繁琐。你的例子变成了
def writeAll[T:Foo] (items: List[T]) = items.foreach(w => implicitly[Foo[T]].write(w)) 它编译完全相同,但是可以很好地清除签名,并且有更少的“噪点”变量浮动。 不是一个很好的答案,但替代方案可能涉及反射,我不知道任何图书馆,只会使这自动工作。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |