如何编写绑定集合类型和元素类型的通用 Scala 增强方法?
How can you can write generic Scala enhancement methods that bind collection type as well as element type?
如果您像我一样,偶尔想为 Scala 集合或序列编写增强方法,但您希望绑定集合类型和元素类型,而不仅仅是向上转换为 Seq[T]。
有一种方法可以做到,它是这样工作的:
object enhance {
import scala.language.higherKinds
import scala.language.implicitConversions
import scala.collection.SeqLike
import scala.collection.generic.CanBuildFrom
implicit class Enhance[T, S[E] <: SeqLike[E, S[E]]](seq: S[T]) {
def first3(implicit cbf: CanBuildFrom[S[T], T, S[T]]) = seq.take(3)
def foo = seq.iterator
def goo(implicit cbf: CanBuildFrom[Nothing, T, S[T]]) = foo.take(3).to[S]
def moo[U](f: T => U)(implicit cbf: CanBuildFrom[S[T], U, S[U]]) = seq.map(f)
}
}
使用上面的类型签名模式,增强的方法可以识别元素类型 T
(例如 Int
或 String
) 和 更高种类的序列类型 S
(例如 List
或 Vector
),因此它可以 return 恰好是调用它的序列类型。
许多序列方法可能需要 CanBuildFrom
隐式,它们作为隐式参数添加到 Enhance
方法中,在上面的示例中需要它们。
以下是示例 运行,显示了所需的更高种类的集合 return 类型:
scala> import enhance._
import enhance._
scala> (1 to 10).toList.first3
res0: List[Int] = List(1, 2, 3)
scala> (1 to 10).toVector.first3
res1: Vector[Int] = Vector(1, 2, 3)
scala> (1 to 10).toList.goo
res2: List[Int] = List(1, 2, 3)
scala> (1 to 10).toVector.goo
res3: Vector[Int] = Vector(1, 2, 3)
scala> (1 to 10).toList.moo(_.toDouble)
res4: List[Double] = List(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
scala> (1 to 10).toVector.moo(_.toDouble)
res5: Vector[Double] = Vector(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
如果您像我一样,偶尔想为 Scala 集合或序列编写增强方法,但您希望绑定集合类型和元素类型,而不仅仅是向上转换为 Seq[T]。
有一种方法可以做到,它是这样工作的:
object enhance {
import scala.language.higherKinds
import scala.language.implicitConversions
import scala.collection.SeqLike
import scala.collection.generic.CanBuildFrom
implicit class Enhance[T, S[E] <: SeqLike[E, S[E]]](seq: S[T]) {
def first3(implicit cbf: CanBuildFrom[S[T], T, S[T]]) = seq.take(3)
def foo = seq.iterator
def goo(implicit cbf: CanBuildFrom[Nothing, T, S[T]]) = foo.take(3).to[S]
def moo[U](f: T => U)(implicit cbf: CanBuildFrom[S[T], U, S[U]]) = seq.map(f)
}
}
使用上面的类型签名模式,增强的方法可以识别元素类型 T
(例如 Int
或 String
) 和 更高种类的序列类型 S
(例如 List
或 Vector
),因此它可以 return 恰好是调用它的序列类型。
许多序列方法可能需要 CanBuildFrom
隐式,它们作为隐式参数添加到 Enhance
方法中,在上面的示例中需要它们。
以下是示例 运行,显示了所需的更高种类的集合 return 类型:
scala> import enhance._
import enhance._
scala> (1 to 10).toList.first3
res0: List[Int] = List(1, 2, 3)
scala> (1 to 10).toVector.first3
res1: Vector[Int] = Vector(1, 2, 3)
scala> (1 to 10).toList.goo
res2: List[Int] = List(1, 2, 3)
scala> (1 to 10).toVector.goo
res3: Vector[Int] = Vector(1, 2, 3)
scala> (1 to 10).toList.moo(_.toDouble)
res4: List[Double] = List(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)
scala> (1 to 10).toVector.moo(_.toDouble)
res5: Vector[Double] = Vector(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)