Ale*_*lcu 11 scala contravariance typeclass implicits
我有这样一个特点:
trait CanFold[-T, R] {
def sum(acc: R, elem: T): R
def zero: R
}
Run Code Online (Sandbox Code Playgroud)
有一个像这样的功能:
def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B =
list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e))
Run Code Online (Sandbox Code Playgroud)
目的是做这样的事情:
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)
Run Code Online (Sandbox Code Playgroud)
所以它是类型的类型,环境已经知道如何折叠,并且可以为Ints,Strings等定义.
我的问题是我想要具有更优先的更具体的含义,如下所示:
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)
Run Code Online (Sandbox Code Playgroud)
然而,该方法调用会产生冲突,因为存在歧义:
both method CanFoldSeqs in object ...
and method CanFoldSets in object ...
match expected type CanFold[Set[Int], B]
Run Code Online (Sandbox Code Playgroud)
所以我想要的是编译器搜索Any和我的类型之间最具体的隐式.目的是为基类型提供默认实现,可以为更具体的子类型轻松覆盖,而不会出现难看的阴影.
我可能在想这里,但人们只能希望:-)
Tra*_*own 15
在这种情况下通常的方法利用了继承优先化的方式:
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._
Run Code Online (Sandbox Code Playgroud)
现在,Set实例将在适用时使用,但是当实例不可用时Traversable仍可使用.
| 归档时间: |
|
| 查看次数: |
508 次 |
| 最近记录: |