Skip to content

Commit

Permalink
Split @milessabin HasRepr into IsTraversableOnce and IsTraversableLik…
Browse files Browse the repository at this point in the history
…e type class-ish things.
  • Loading branch information
jsuereth committed Jun 27, 2012
1 parent cbcca2c commit f40e521
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 55 deletions.
9 changes: 0 additions & 9 deletions src/library/scala/collection/GenTraversableLike.scala
Expand Up @@ -411,12 +411,3 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with
def stringPrefix: String

}

object GenTraversableLike {
/** Manufacture a conversion from collection representation type `Repr` to
* its corresponding `GenTraversableLike` given an implicitly available
* instance of `FromRepr[Repr]`.
* @see [[scala.collection.generic.FromRepr]]
*/
implicit def fromRepr[Repr](implicit fr : FromRepr[Repr]) = fr.hasElem
}
Expand Up @@ -18,39 +18,41 @@ package generic
*
* Example usage,
* {{{
* import scala.collection.generic.{ CanBuildFrom, FromRepr, HasElem }
*
* class FilterMapImpl[A, Repr](val r : Repr)(implicit hasElem : HasElem[Repr, A]) {
* def filterMap[B, That](f : A => Option[B])
* (implicit cbf : CanBuildFrom[Repr, B, That]) : That = r.flatMap(f(_).toSeq)
* class FilterMapImpl[A, Repr](val r: GenTraversableLike[A, Repr]) {
* final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That =
* r.flatMap(f(_).toSeq)
* }
*
* implicit def filterMap[Repr : FromRepr](r : Repr) = new FilterMapImpl(r)
* implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsTraversableOnce[Repr]): FilterMapImpl[fr.A,Repr] =
* new FilterMapImpl(fr.conversion(r))
*
* val l = List(1, 2, 3, 4, 5)
* List(1, 2, 3, 4, 5) filterMap (i => if(i % 2 == 0) Some(i) else None)
* // == List(2, 4)
* }}}
*
* @author Miles Sabin
* @author J. Suereth
* @since 2.10
*/
trait FromRepr[Repr] {
trait IsTraversableLike[Repr] {
/** The type of elements we can traverse over. */
type A
val hasElem: HasElem[Repr, A]
/** A conversion from the representation type `Repr` to a `GenTraversableLike[A,Repr]`. */
val conversion: Repr => GenTraversableLike[A, Repr]
}

object FromRepr {
object IsTraversableLike {
import language.higherKinds

implicit val stringFromRepr : FromRepr[String] { type A = Char } = new FromRepr[String] {
type A = Char
val hasElem = implicitly[HasElem[String, Char]]
}
implicit val stringRepr: IsTraversableLike[String] { type A = Char } =
new IsTraversableLike[String] {
type A = Char
val conversion = implicitly[String => GenTraversableLike[Char, String]]
}

implicit def genTraversableLikeFromRepr[C[_], A0]
(implicit hasElem0: HasElem[C[A0], A0]) : FromRepr[C[A0]] { type A = A0 } = new FromRepr[C[A0]] {
implicit def genTraversableLikeRepr[C[_], A0](implicit conv: C[A0] => GenTraversableLike[A0,C[A0]]): IsTraversableLike[C[A0]] { type A = A0 } =
new IsTraversableLike[C[A0]] {
type A = A0
val hasElem = hasElem0
val conversion = conv
}
}
62 changes: 62 additions & 0 deletions src/library/scala/collection/generic/IsTraversableOnce.scala
@@ -0,0 +1,62 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */

package scala.collection
package generic

/** Type class witnessing that a collection representation type `Repr` has
* elements of type `A` and has a conversion to `GenTraversableOnce[A]`.
*
* This type enables simple enrichment of `GenTraversableOnce`s with extension
* methods which can make full use of the mechanics of the Scala collections
* framework in their implementation.
*
* Example usage,
* {{{
* class FilterMapImpl[A, Repr](val r: GenTraversableOnce[A]) {
* final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That = {
* val b = cbf()
* for(e <- r.seq) f(e) foreach (b +=)
* b.result
* }
* }
* implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsTraversableOnce[Repr]): FilterMapImpl[fr.A,Repr] =
* new FilterMapImpl[fr.A, Repr](fr.conversion(r))
*
* val l = List(1, 2, 3, 4, 5)
* List(1, 2, 3, 4, 5) filterMap (i => if(i % 2 == 0) Some(i) else None)
* // == List(2, 4)
* }}}
*
* @author Miles Sabin
* @author J. Suereth
* @since 2.10
*/
trait IsTraversableOnce[Repr] {
/** The type of elements we can traverse over. */
type A
/** A conversion from the representation type `Repr` to a `GenTraversableOnce[A]`. */
val conversion: Repr => GenTraversableOnce[A]
}

object IsTraversableOnce {
import language.higherKinds

implicit val stringRepr: IsTraversableOnce[String] { type A = Char } =
new IsTraversableOnce[String] {
type A = Char
val conversion = implicitly[String => GenTraversableOnce[Char]]
}

implicit def genTraversableLikeRepr[C[_], A0](implicit conv: C[A0] => GenTraversableOnce[A0]): IsTraversableOnce[C[A0]] { type A = A0 } =
new IsTraversableOnce[C[A0]] {
type A = A0
val conversion = conv
}
}

8 changes: 1 addition & 7 deletions src/library/scala/collection/generic/package.scala
Expand Up @@ -6,12 +6,6 @@ import language.higherKinds
package object generic {
type CanBuild[-Elem, +To] = CanBuildFrom[Nothing, Elem, To]

/** The type of conversions from a collection representation type
* `Repr` to its corresponding GenTraversableLike.
* @see [[scala.collection.generic.FromRepr]]
*/
type HasElem[Repr, A] = Repr => GenTraversableLike[A, Repr]

@deprecated("use ClassTagTraversableFactory instead", "2.10.0")
type ClassManifestTraversableFactory[CC[X] <: Traversable[X] with GenericClassManifestTraversableTemplate[X, CC]] = ClassTagTraversableFactory[CC]

Expand All @@ -20,4 +14,4 @@ package object generic {

@deprecated("use GenericClassTagTraversableTemplate instead", "2.10.0")
type GenericClassManifestTraversableTemplate[+A, +CC[X] <: Traversable[X]] = GenericClassTagTraversableTemplate[A, CC]
}
}
4 changes: 4 additions & 0 deletions test/files/run/enrich-gentraversable.check
Expand Up @@ -2,3 +2,7 @@ List(2, 4)
Array(2, 4)
HW
Vector(72, 108, 108, 32, 114, 108, 100)
List(2, 4)
Array(2, 4)
HW
Vector(72, 108, 108, 32, 114, 108, 100)
81 changes: 59 additions & 22 deletions test/files/run/enrich-gentraversable.scala
@@ -1,30 +1,67 @@
object Test extends App {
import scala.collection.generic.{ CanBuildFrom, FromRepr, HasElem }
import scala.collection.{GenTraversableOnce,GenTraversableLike}
import scala.collection.generic._

def typed[T](t : => T) {}

class FilterMapImpl[A, Repr](val r : Repr)(implicit hasElem : HasElem[Repr, A]) {
def filterMap[B, That](f : A => Option[B])(implicit cbf : CanBuildFrom[Repr, B, That]) : That = r.flatMap(f(_).toSeq)
def testTraversableLike = {
class FilterMapImpl[A, Repr](val r: GenTraversableLike[A, Repr]) /* extends AnyVal */ {
final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That =
r.flatMap(f(_).toSeq)
}
implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsTraversableLike[Repr]): FilterMapImpl[fr.A,Repr] =
new FilterMapImpl[fr.A, Repr](fr.conversion(r))

val l = List(1, 2, 3, 4, 5)
val fml = l.filterMap(i => if(i % 2 == 0) Some(i) else None)
typed[List[Int]](fml)
println(fml)

val a = Array(1, 2, 3, 4, 5)
val fma = a.filterMap(i => if(i % 2 == 0) Some(i) else None)
typed[Array[Int]](fma)
println(fma.deep)

val s = "Hello World"
val fms1 = s.filterMap(c => if(c >= 'A' && c <= 'Z') Some(c) else None)
typed[String](fms1)
println(fms1)

val fms2 = s.filterMap(c =>if(c % 2 == 0) Some(c.toInt) else None)
typed[IndexedSeq[Int]](fms2)
println(fms2)
}
def testTraversableOnce = {
class FilterMapImpl[A, Repr](val r: GenTraversableOnce[A]) /* extends AnyVal */ {
final def filterMap[B, That](f: A => Option[B])(implicit cbf: CanBuildFrom[Repr, B, That]): That = {
val b = cbf()
for(e <- r.seq) f(e) foreach (b +=)

implicit def filterMap[Repr : FromRepr](r : Repr) = new FilterMapImpl(r)

val l = List(1, 2, 3, 4, 5)
val fml = l.filterMap(i => if(i % 2 == 0) Some(i) else None)
typed[List[Int]](fml)
println(fml)

val a = Array(1, 2, 3, 4, 5)
val fma = a.filterMap(i => if(i % 2 == 0) Some(i) else None)
typed[Array[Int]](fma)
println(fma.deep)
b.result
}
}
implicit def filterMap[Repr, A](r: Repr)(implicit fr: IsTraversableOnce[Repr]): FilterMapImpl[fr.A,Repr] =
new FilterMapImpl[fr.A, Repr](fr.conversion(r))

val s = "Hello World"
val fms1 = s.filterMap(c => if(c >= 'A' && c <= 'Z') Some(c) else None)
typed[String](fms1)
println(fms1)
val l = List(1, 2, 3, 4, 5)
val fml = l.filterMap(i => if(i % 2 == 0) Some(i) else None)
typed[List[Int]](fml)
println(fml)

val fms2 = s.filterMap(c =>if(c % 2 == 0) Some(c.toInt) else None)
typed[IndexedSeq[Int]](fms2)
println(fms2)
val a = Array(1, 2, 3, 4, 5)
val fma = a.filterMap(i => if(i % 2 == 0) Some(i) else None)
typed[Array[Int]](fma)
println(fma.deep)

val s = "Hello World"
val fms1 = s.filterMap(c => if(c >= 'A' && c <= 'Z') Some(c) else None)
typed[String](fms1)
println(fms1)

val fms2 = s.filterMap(c =>if(c % 2 == 0) Some(c.toInt) else None)
typed[IndexedSeq[Int]](fms2)
println(fms2)
}

testTraversableLike
testTraversableOnce
}

0 comments on commit f40e521

Please sign in to comment.