Scala 中 Traversable 内容的隐式转换
Implicit conversion of Traversable contents in Scala
我正在尝试创建一个隐式转换器,它将使用当前在范围 (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
的任何子类?
您已将 convertLists
明确定义为 return Traversable[B]
。 Traversable
不是 List
的子类型(它是它的超类型),因此 convertLists
(Traversable
) 的结果不能是 return 类型的 listOfB
(List
).
如果使用 CanBuildFrom
:
,您可以定义 convertLists
以根据其参数类型推断结果类型
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))
使用 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)
我正在尝试创建一个隐式转换器,它将使用当前在范围 (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
的任何子类?
您已将 convertLists
明确定义为 return Traversable[B]
。 Traversable
不是 List
的子类型(它是它的超类型),因此 convertLists
(Traversable
) 的结果不能是 return 类型的 listOfB
(List
).
如果使用 CanBuildFrom
:
convertLists
以根据其参数类型推断结果类型
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))
使用 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)