我无法进行隐式转换List [A] =>列表[B],给出隐式转换A => B.
有一个非常related question that has a solution but does not work for me。此外,这是一个很好的documentation for chaining implicits,我用它作为我的代码的基础。
我尝试在下面的代码中提出的观点是,链接implicits在所有预期的情况下都能正常工作,即使对于类似集合的对象,例如下面的Container
,但集合失败了:
object ChainImplicits extends App{
case class A(n: Int)
implicit def toA(n: Int): A = A(n)
case class B(m: Int, n: Int)
implicit def aToB[T](a: T)(implicit f: T => A): B = B(a.n, a.n)
case class C(m: Int, n: Int, o: Int) {
def total = m + n + o
}
implicit def bToC[T](b: T)(implicit f: T => B): C = C(b.m, b.n, b.m + b.n)
// works
println(5.total)
println(new A(5).total)
println(new B(5, 5).total)
println(new C(5, 5, 10).total)
case class Container[T](value:T) {
def map[B](f: T => B) = Container(f(value))
}
implicit def ContainerConv[A,B](container:Container[A])
(implicit f: A => B): Container[B] = container.map(f)
val container = Container(1)
container.value.total //Works, as expected
def containerCTotal(containerC: Container[C]) = containerC.value.total
containerCTotal(container) //Works too!
implicit def listConv[A,B](collection: List[A])
(implicit f: A => B): List[B] = collection.map(f)
val list = List(1)
def CTotals(list: List[C]) = list.map(_.total)
CTotals(listConv(list)) //Explicit conversion works, finds the chain implicit conversions Int => C :)
CTotals(list) //... but implicit does not :(
def ATotals(list: List[A]) = list.map(_.total)
ATotals(list) // Simple (non-chained) conversion of contained values does not work either :(
}
如何使这些最后的转化有效?
我还尝试了(已弃用的)视图边界,得到了相同的结果:
implicit def convert[B, A <% B](l: List[A]): List[B] = l map { a => a: B }
以防万一,编译错误是预期的:
type mismatch;
found : List[Int]
required: List[ChainImplicits.C]
CTotals(list) //... but implicit does not :(
同样适用于ATotals(list)
我在scala版本2.11.8和2.11.4上尝试过它。
更新
我在Andreas&#39;之后证实了评论基础问题与List协变有关。给上面的Container
类提供协方差(即Container[+A]
)会使containerCTotal(container)
之前有效的隐式转换失败。