Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split @milessabin HasRepr into IsTraversableOnce and IsTraversableLik…
…e type class-ish things.
- Loading branch information
Showing
6 changed files
with
145 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
src/library/scala/collection/generic/IsTraversableOnce.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |