scala – 如何避免具有多个Type Class关系的模糊转换链?
在我的库中,我有三个类型类:
trait Monoid[T] { val zero : T def sum(x : T,y : T) : T } trait AbelianGroup[T] extends Monoid[T] { def inverse(x : T) : T def difference(x : T,y : T) : T } //represents types that are represents lists with a fixed number of elements,such as //the tuple type (Int,Int) trait Vector[T,U] { ... } 在以下条件下,这些类型类可以相互转换: >如果类型T是scala.math.Numeric类型,则它也是AbelianGroup. 例如,因为(Int,Int)是Int over Int类型,而Int是AbelianGroup,所以(Int,Int)也是AbelianGroup. 这些关系和其他关系很容易在伴侣类中实现,如下所示: object Monoid { implicit def fromAbelianGroup[T : AbelianGroup] : Monoid[T] = implicitly[AbelianGroup[T]] implicit def fromVector[T : Vector[T,U],U : Monoid] : Monid[T] = ... } object AbelianGroup { implicit def fromNumeric[T : Numeric] : AbelianGroup[T] = ... implicit def fromOtherTypeX[T : ...] : AbelianGroup[T] ... implicit def fromVector[T : Vector[T,U : AbelianGroup] : AbelianGroup[T] = ... } 这很好用,直到你尝试使用类似元组类型(Int,Int)之类的东西作为Monoid.编译器找到两种方法来获得这种类型的Monoid类型类对象: > Monoid.fromAbelianGroup(AbelianGroup.fromVector(Vector.from2Tuple, 为了解决这种歧义,我修改了Monoid伴随类,以包含从Numeric(以及可直接转换为AbelianGroup的其他类型)的直接转换. /*revised*/ object Monoid { //implicit def fromAbelianGroup[T : AbelianGroup] : Monoid[T] = implicitly[AbelianGroup[T]] implicit def fromNumeric[T : Numeric] : Monoid[T] = ... //<-- redundant implicit def fromOtherTypeX[T : ...] : AbelianGroup[T] = ... //<-- redundant ... implicit def fromVector[T : Vector[T,U : Monoid] : Monid[T] = ... } object AbelianGroup { implicit def fromNumeric[T : Numeric] : AbelianGroup[T] = ... implicit def fromOtherTypeX[T : ...] : AbelianGroup[T] = ... ... implicit def fromVector[T : Vector[T,U : AbelianGroup] : AbelianGroup[T] = ... } 然而,这有点令人不满意,因为它基本上违反了DRY委托人.当我为AbelianGroups添加新的实现时,我将不得不在两个伴随对象中实现转换,就像我为Numeric和OtherTypeX做的那样,等等.所以,我觉得我在某个地方做了一个错误的转向. 有没有办法修改我的代码以避免这种冗余并解决编译时模糊错误?这种情况下的最佳做法是什么? 解决方法
你可以
move the implicits for which you want to have lower priority into a supertype of the companion object:
trait LowPriorityMonoidImplicits { implicit def fromVector[T : Vector[T,U : Monoid] : Monoid[T] = ... } object Monoid extends LowPriorityMonoidImplicits { implicit def fromAbelianGroup[T : AbelianGroup] : Monoid[T] = implicitly[AbelianGroup[T]] } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |