Scala-应用于隐式参数选择的协方差/反方差
我有这样一个特点:Scala-应用于隐式参数选择的协方差/反方差,scala,typeclass,contravariance,implicits,Scala,Typeclass,Contravariance,Implicits,我有这样一个特点: trait CanFold[-T, R] { def sum(acc: R, elem: T): R def zero: R } def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B = list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e)) implicit def CanFoldSeqs[A] = new C
trait CanFold[-T, R] {
def sum(acc: R, elem: T): R
def zero: R
}
def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))
implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
def zero = Traversable()
}
sum(List(1, 2, 3) :: List(4, 5) :: Nil)
//=> Traversable[Int] = List(1, 2, 3, 4, 5)
implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
def sum(x: Set[A], y: Set[A]) = x ++ y
def zero = Set.empty[A]
}
sum(Set(1,2) :: Set(3,4) :: Nil)
//=> Set[Int] = Set(1, 2, 3, 4)
其功能如下所示:
trait CanFold[-T, R] {
def sum(acc: R, elem: T): R
def zero: R
}
def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))
implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
def zero = Traversable()
}
sum(List(1, 2, 3) :: List(4, 5) :: Nil)
//=> Traversable[Int] = List(1, 2, 3, 4, 5)
implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
def sum(x: Set[A], y: Set[A]) = x ++ y
def zero = Set.empty[A]
}
sum(Set(1,2) :: Set(3,4) :: Nil)
//=> Set[Int] = Set(1, 2, 3, 4)
这样做的目的是:
trait CanFold[-T, R] {
def sum(acc: R, elem: T): R
def zero: R
}
def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))
implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
def zero = Traversable()
}
sum(List(1, 2, 3) :: List(4, 5) :: Nil)
//=> Traversable[Int] = List(1, 2, 3, 4, 5)
implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
def sum(x: Set[A], y: Set[A]) = x ++ y
def zero = Set.empty[A]
}
sum(Set(1,2) :: Set(3,4) :: Nil)
//=> Set[Int] = Set(1, 2, 3, 4)
因此,它是一个类型类,用于环境已经知道如何折叠的类型,并且可以为int、string等定义类型
我的问题是,我还希望有更具体的优先含义,如:
trait CanFold[-T, R] {
def sum(acc: R, elem: T): R
def zero: R
}
def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))
implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
def zero = Traversable()
}
sum(List(1, 2, 3) :: List(4, 5) :: Nil)
//=> Traversable[Int] = List(1, 2, 3, 4, 5)
implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
def sum(x: Set[A], y: Set[A]) = x ++ y
def zero = Set.empty[A]
}
sum(Set(1,2) :: Set(3,4) :: Nil)
//=> Set[Int] = Set(1, 2, 3, 4)
但是,该方法调用会产生冲突,因为存在歧义:
both method CanFoldSeqs in object ...
and method CanFoldSets in object ...
match expected type CanFold[Set[Int], B]
因此,我希望编译器搜索任意类型和我的类型之间最具体的隐式。其目的是为基类型提供默认实现,这些基类型可以很容易地为更具体的子类型覆盖,而不需要隐藏(这很难看)
在这里,我可能会满怀希望地思考,但人们只能希望:-)在这种情况下,通常的方法利用了继承对隐含内容进行优先排序的方式:
trait LowPriorityCanFoldInstances {
implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] {
def sum(x: Traversable[A], y: Traversable[A]) = x ++ y
def zero = Traversable()
}
}
object CanFoldInstances extends LowPriorityCanFoldInstances {
implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] {
def sum(x: Set[A], y: Set[A]) = x ++ y
def zero = Set.empty[A]
}
}
import CanFoldInstances._
现在,Set
实例在适用时将被使用,但Traversable
实例在不适用时仍然可用