Skip to content

Commit f40e521

Browse files
committed
Split @milessabin HasRepr into IsTraversableOnce and IsTraversableLike type class-ish things.
1 parent cbcca2c commit f40e521

File tree

6 files changed

+145
-55
lines changed

6 files changed

+145
-55
lines changed

src/library/scala/collection/GenTraversableLike.scala

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,3 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with
411411
def stringPrefix: String
412412

413413
}
414-
415-
object GenTraversableLike {
416-
/** Manufacture a conversion from collection representation type `Repr` to
417-
* its corresponding `GenTraversableLike` given an implicitly available
418-
* instance of `FromRepr[Repr]`.
419-
* @see [[scala.collection.generic.FromRepr]]
420-
*/
421-
implicit def fromRepr[Repr](implicit fr : FromRepr[Repr]) = fr.hasElem
422-
}

src/library/scala/collection/generic/FromRepr.scala renamed to src/library/scala/collection/generic/IsTraversableLike.scala

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,41 @@ package generic
1818
*
1919
* Example usage,
2020
* {{{
21-
* import scala.collection.generic.{ CanBuildFrom, FromRepr, HasElem }
22-
*
23-
* class FilterMapImpl[A, Repr](val r : Repr)(implicit hasElem : HasElem[Repr, A]) {
24-
* def filterMap[B, That](f : A => Option[B])
25-
* (implicit cbf : CanBuildFrom[Repr, B, That]) : That = r.flatMap(f(_).toSeq)
21+
* class FilterMapImpl[A, Repr](val r: GenTraversableLike[A, Repr]) {
22+
* final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That =
23+
* r.flatMap(f(_).toSeq)
2624
* }
27-
*
28-
* implicit def filterMap[Repr : FromRepr](r : Repr) = new FilterMapImpl(r)
25+
* implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsTraversableOnce[Repr]): FilterMapImpl[fr.A,Repr] =
26+
* new FilterMapImpl(fr.conversion(r))
2927
*
3028
* val l = List(1, 2, 3, 4, 5)
3129
* List(1, 2, 3, 4, 5) filterMap (i => if(i % 2 == 0) Some(i) else None)
3230
* // == List(2, 4)
3331
* }}}
3432
*
3533
* @author Miles Sabin
34+
* @author J. Suereth
3635
* @since 2.10
3736
*/
38-
trait FromRepr[Repr] {
37+
trait IsTraversableLike[Repr] {
38+
/** The type of elements we can traverse over. */
3939
type A
40-
val hasElem: HasElem[Repr, A]
40+
/** A conversion from the representation type `Repr` to a `GenTraversableLike[A,Repr]`. */
41+
val conversion: Repr => GenTraversableLike[A, Repr]
4142
}
4243

43-
object FromRepr {
44+
object IsTraversableLike {
4445
import language.higherKinds
4546

46-
implicit val stringFromRepr : FromRepr[String] { type A = Char } = new FromRepr[String] {
47-
type A = Char
48-
val hasElem = implicitly[HasElem[String, Char]]
49-
}
47+
implicit val stringRepr: IsTraversableLike[String] { type A = Char } =
48+
new IsTraversableLike[String] {
49+
type A = Char
50+
val conversion = implicitly[String => GenTraversableLike[Char, String]]
51+
}
5052

51-
implicit def genTraversableLikeFromRepr[C[_], A0]
52-
(implicit hasElem0: HasElem[C[A0], A0]) : FromRepr[C[A0]] { type A = A0 } = new FromRepr[C[A0]] {
53+
implicit def genTraversableLikeRepr[C[_], A0](implicit conv: C[A0] => GenTraversableLike[A0,C[A0]]): IsTraversableLike[C[A0]] { type A = A0 } =
54+
new IsTraversableLike[C[A0]] {
5355
type A = A0
54-
val hasElem = hasElem0
56+
val conversion = conv
5557
}
5658
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* __ *\
2+
** ________ ___ / / ___ Scala API **
3+
** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL **
4+
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
5+
** /____/\___/_/ |_/____/_/ | | **
6+
** |/ **
7+
\* */
8+
9+
package scala.collection
10+
package generic
11+
12+
/** Type class witnessing that a collection representation type `Repr` has
13+
* elements of type `A` and has a conversion to `GenTraversableOnce[A]`.
14+
*
15+
* This type enables simple enrichment of `GenTraversableOnce`s with extension
16+
* methods which can make full use of the mechanics of the Scala collections
17+
* framework in their implementation.
18+
*
19+
* Example usage,
20+
* {{{
21+
* class FilterMapImpl[A, Repr](val r: GenTraversableOnce[A]) {
22+
* final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That = {
23+
* val b = cbf()
24+
* for(e <- r.seq) f(e) foreach (b +=)
25+
* b.result
26+
* }
27+
* }
28+
* implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsTraversableOnce[Repr]): FilterMapImpl[fr.A,Repr] =
29+
* new FilterMapImpl[fr.A, Repr](fr.conversion(r))
30+
*
31+
* val l = List(1, 2, 3, 4, 5)
32+
* List(1, 2, 3, 4, 5) filterMap (i => if(i % 2 == 0) Some(i) else None)
33+
* // == List(2, 4)
34+
* }}}
35+
*
36+
* @author Miles Sabin
37+
* @author J. Suereth
38+
* @since 2.10
39+
*/
40+
trait IsTraversableOnce[Repr] {
41+
/** The type of elements we can traverse over. */
42+
type A
43+
/** A conversion from the representation type `Repr` to a `GenTraversableOnce[A]`. */
44+
val conversion: Repr => GenTraversableOnce[A]
45+
}
46+
47+
object IsTraversableOnce {
48+
import language.higherKinds
49+
50+
implicit val stringRepr: IsTraversableOnce[String] { type A = Char } =
51+
new IsTraversableOnce[String] {
52+
type A = Char
53+
val conversion = implicitly[String => GenTraversableOnce[Char]]
54+
}
55+
56+
implicit def genTraversableLikeRepr[C[_], A0](implicit conv: C[A0] => GenTraversableOnce[A0]): IsTraversableOnce[C[A0]] { type A = A0 } =
57+
new IsTraversableOnce[C[A0]] {
58+
type A = A0
59+
val conversion = conv
60+
}
61+
}
62+

src/library/scala/collection/generic/package.scala

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@ import language.higherKinds
66
package object generic {
77
type CanBuild[-Elem, +To] = CanBuildFrom[Nothing, Elem, To]
88

9-
/** The type of conversions from a collection representation type
10-
* `Repr` to its corresponding GenTraversableLike.
11-
* @see [[scala.collection.generic.FromRepr]]
12-
*/
13-
type HasElem[Repr, A] = Repr => GenTraversableLike[A, Repr]
14-
159
@deprecated("use ClassTagTraversableFactory instead", "2.10.0")
1610
type ClassManifestTraversableFactory[CC[X] <: Traversable[X] with GenericClassManifestTraversableTemplate[X, CC]] = ClassTagTraversableFactory[CC]
1711

@@ -20,4 +14,4 @@ package object generic {
2014

2115
@deprecated("use GenericClassTagTraversableTemplate instead", "2.10.0")
2216
type GenericClassManifestTraversableTemplate[+A, +CC[X] <: Traversable[X]] = GenericClassTagTraversableTemplate[A, CC]
23-
}
17+
}

test/files/run/enrich-gentraversable.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@ List(2, 4)
22
Array(2, 4)
33
HW
44
Vector(72, 108, 108, 32, 114, 108, 100)
5+
List(2, 4)
6+
Array(2, 4)
7+
HW
8+
Vector(72, 108, 108, 32, 114, 108, 100)
Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,67 @@
11
object Test extends App {
2-
import scala.collection.generic.{ CanBuildFrom, FromRepr, HasElem }
2+
import scala.collection.{GenTraversableOnce,GenTraversableLike}
3+
import scala.collection.generic._
34

45
def typed[T](t : => T) {}
5-
6-
class FilterMapImpl[A, Repr](val r : Repr)(implicit hasElem : HasElem[Repr, A]) {
7-
def filterMap[B, That](f : A => Option[B])(implicit cbf : CanBuildFrom[Repr, B, That]) : That = r.flatMap(f(_).toSeq)
6+
def testTraversableLike = {
7+
class FilterMapImpl[A, Repr](val r: GenTraversableLike[A, Repr]) /* extends AnyVal */ {
8+
final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That =
9+
r.flatMap(f(_).toSeq)
10+
}
11+
implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsTraversableLike[Repr]): FilterMapImpl[fr.A,Repr] =
12+
new FilterMapImpl[fr.A, Repr](fr.conversion(r))
13+
14+
val l = List(1, 2, 3, 4, 5)
15+
val fml = l.filterMap(i => if(i % 2 == 0) Some(i) else None)
16+
typed[List[Int]](fml)
17+
println(fml)
18+
19+
val a = Array(1, 2, 3, 4, 5)
20+
val fma = a.filterMap(i => if(i % 2 == 0) Some(i) else None)
21+
typed[Array[Int]](fma)
22+
println(fma.deep)
23+
24+
val s = "Hello World"
25+
val fms1 = s.filterMap(c => if(c >= 'A' && c <= 'Z') Some(c) else None)
26+
typed[String](fms1)
27+
println(fms1)
28+
29+
val fms2 = s.filterMap(c =>if(c % 2 == 0) Some(c.toInt) else None)
30+
typed[IndexedSeq[Int]](fms2)
31+
println(fms2)
832
}
33+
def testTraversableOnce = {
34+
class FilterMapImpl[A, Repr](val r: GenTraversableOnce[A]) /* extends AnyVal */ {
35+
final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That = {
36+
val b = cbf()
37+
for(e <- r.seq) f(e) foreach (b +=)
938

10-
implicit def filterMap[Repr : FromRepr](r : Repr) = new FilterMapImpl(r)
11-
12-
val l = List(1, 2, 3, 4, 5)
13-
val fml = l.filterMap(i => if(i % 2 == 0) Some(i) else None)
14-
typed[List[Int]](fml)
15-
println(fml)
16-
17-
val a = Array(1, 2, 3, 4, 5)
18-
val fma = a.filterMap(i => if(i % 2 == 0) Some(i) else None)
19-
typed[Array[Int]](fma)
20-
println(fma.deep)
39+
b.result
40+
}
41+
}
42+
implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsTraversableOnce[Repr]): FilterMapImpl[fr.A,Repr] =
43+
new FilterMapImpl[fr.A, Repr](fr.conversion(r))
2144

22-
val s = "Hello World"
23-
val fms1 = s.filterMap(c => if(c >= 'A' && c <= 'Z') Some(c) else None)
24-
typed[String](fms1)
25-
println(fms1)
45+
val l = List(1, 2, 3, 4, 5)
46+
val fml = l.filterMap(i => if(i % 2 == 0) Some(i) else None)
47+
typed[List[Int]](fml)
48+
println(fml)
2649

27-
val fms2 = s.filterMap(c =>if(c % 2 == 0) Some(c.toInt) else None)
28-
typed[IndexedSeq[Int]](fms2)
29-
println(fms2)
50+
val a = Array(1, 2, 3, 4, 5)
51+
val fma = a.filterMap(i => if(i % 2 == 0) Some(i) else None)
52+
typed[Array[Int]](fma)
53+
println(fma.deep)
54+
55+
val s = "Hello World"
56+
val fms1 = s.filterMap(c => if(c >= 'A' && c <= 'Z') Some(c) else None)
57+
typed[String](fms1)
58+
println(fms1)
59+
60+
val fms2 = s.filterMap(c =>if(c % 2 == 0) Some(c.toInt) else None)
61+
typed[IndexedSeq[Int]](fms2)
62+
println(fms2)
63+
}
64+
65+
testTraversableLike
66+
testTraversableOnce
3067
}

0 commit comments

Comments
 (0)