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]]
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
