回答

7

有一种方法来做到这一点,并且它是这样工作的:

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(例如IntString更高主观序列类型S(例如ListVector),因此它可以精确地返回它被调用的序列类型。

许多序列方法可能需要CanBuildFrom含义,将它们作为隐含参数添加到Enhance方法中,在上述示例中需要它们。

以下是一个样品运行,显示出期望的-kinded更高集合返回类型:

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

您也可以定义类作为'隐类增强[T,S [E] <:IterableLike [E,S [se]:(seq:S [T]){'然后你将不需要'asInstanceOf' –

+3

如果你使用'map'或其他方法在新方法中使用'CanBuildFrom'实现。结果会以“Seq”出现。您需要将相关的隐式'CanBuildFrom'传递给'Enhance'类或该方法。 – Kolmar

+1

谢谢@НиколайМитропольский和Kolmar,这两个修改都非常有用!我重新编写了我的原始答案,以表明他们的行动。 – eje

相关问题