Odpowiedz

7

Jest sposób, aby to zrobić, i to działa tak:

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

Stosując wzór rodzaj podpisu powyżej, ulepszone metody są świadomi zarówno typu elementu T (np Int lub String) i typem o wyższej ładowności typu S (np. List lub Vector), dzięki czemu może on zwrócić dokładnie ten typ sekwencji, na który został wywołany.

Wiele metod sekwencji może wymagać CanBuildFrom implicits, które są dodawane do metod jako niejawne parametry, gdzie są potrzebne w powyższych przykładach.

Poniżej bieg próbkę, wykazując pożądane wyższe kinded rodzajów powrotne kolekcji:

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

Również można określić klasę jako 'ukryte klasy Ulepsz [T, S [k] <: IterableLike [E, S [E]]] (seq: S [T]) {'i wtedy nie będziesz potrzebował' asInstanceOf ' –

+3

To nie zadziała, jeśli użyjesz' map' lub jakiejkolwiek innej metody, która bierze 'CanBuildFrom' w nowej metodzie wdrożenia. Rezultat wypadłby po prostu jako "Seq". Musiałbyś przekazać odpowiedni niejawny 'CanBuildFrom' do klasy' Enhance' lub do metody. – Kolmar

+1

Dzięki @ НиколайМитропольский i Kolmar, obie te modyfikacje są bardzo przydatne! Przebudowałem swoją oryginalną odpowiedź, aby pokazać je w akcji. – eje