2016-03-21 59 views
4

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

到目前为止我:

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

然而,这并不与工作:

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

如果我改变TraversableList,然后正常工作,如:

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

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

+0

如果您正确定义隐式转换,它将按预期工作。你看到了什么错误。 –

+1

我认为问题在于你的方法返回'Traversable [B]',但'listOfB'的类型参数是'List [B]'。 –

+0

@EndeNeu但'List'是'Traversable'的子类 –

回答

2

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

可以定义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) 

现在假设A以下简单的定义和B

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)) 
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)