Scala中Traversable内容的隐式转换

时间:2016-03-21 12:24:51

标签: scala implicit-conversion

我正在尝试创建一个隐式转换器,它将使用当前在范围(eg. A => B)中的隐式转换器,并且能够将任何类型的Traversable[A]转换为Traversable[B]

到目前为止,我得到了:

implicit def convertLists[A, B](from: Traversable[A])(implicit conv: A => B): Traversable[B] = from.map(conv)

然而,这不适用于:

val listOfB: List[B] = convertLists(List[A]())

如果我将Traversable更改为List,那么它可以正常工作,例如:

implicit def convertLists[A, B](from: List[A])(implicit conv: A => B): List[B] = from.map(conv)

我是否需要添加其他内容以允许转换器接受Traversable的任何子类?

2 个答案:

答案 0 :(得分:2)

您已明确定义convertLists以返回Traversable[B]Traversable不是List的子类型(它是超类型),因此convertListsTraversable)的结果不能是listOfB的返回类型(List)。

如果使用convertLists,您可以定义CanBuildFrom以根据参数的类型推断结果类型:

import scala.collection.TraversableLike
import scala.collection.generic.CanBuildFrom
import scala.language.higherKinds

// `CC` is some concrete subtype of `Traversable`
// `That` is an automatically inferred result collection type
implicit def convertLists[A, B, CC[T] <: TraversableLike[T, CC[T]], That](
  from: CC[A]
)(
  implicit
    conv: A => B,
    // witness that it's possible to build 
    // a collection with elements `B` from a collection `CC[A]`, 
    // and compute the resulting collection type `That`
    bf: CanBuildFrom[CC[A], B, That]
): That = from.map(conv)

现在假设AB

的以下简单定义
case class A(i: Int)
case class B(i: Int)
implicit def aisb(a: A): B = B(a.i)

以下作品:

val listOfB: List[B] = convertLists(List[A](A(1)))

您无需明确致电convertLists

val listOfB2: List[B] = List[A](A(1))

答案 1 :(得分:2)

使用scala集合库中的方法,您可以得到这样的代码:

import scala.collection.generic.CanBuildFrom
import scala.collection.TraversableLike

implicit val boolToInt = (b: Boolean) => if (b) 1 else 0
implicit def convertLists[A, B, Repr, That](from: TraversableLike[A, Repr])(implicit conv: A => B, bf: CanBuildFrom[Repr, B, That]): That = from map conv
val listOfB: List[Int] = List(true, false)

给出了

listOfB: List[Int] = List(1, 0)