diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala index eaec7a2a7612..0d512306239d 100644 --- a/src/library/scala/collection/GenTraversableLike.scala +++ b/src/library/scala/collection/GenTraversableLike.scala @@ -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 -} diff --git a/src/library/scala/collection/generic/FromRepr.scala b/src/library/scala/collection/generic/IsTraversableLike.scala similarity index 53% rename from src/library/scala/collection/generic/FromRepr.scala rename to src/library/scala/collection/generic/IsTraversableLike.scala index c08761332c61..728832290303 100644 --- a/src/library/scala/collection/generic/FromRepr.scala +++ b/src/library/scala/collection/generic/IsTraversableLike.scala @@ -18,14 +18,12 @@ 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) @@ -33,24 +31,28 @@ package generic * }}} * * @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 } } diff --git a/src/library/scala/collection/generic/IsTraversableOnce.scala b/src/library/scala/collection/generic/IsTraversableOnce.scala new file mode 100644 index 000000000000..b3365532317e --- /dev/null +++ b/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 + } +} + diff --git a/src/library/scala/collection/generic/package.scala b/src/library/scala/collection/generic/package.scala index 85b9995f2e3b..6eecb5e3ff62 100644 --- a/src/library/scala/collection/generic/package.scala +++ b/src/library/scala/collection/generic/package.scala @@ -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] @@ -20,4 +14,4 @@ package object generic { @deprecated("use GenericClassTagTraversableTemplate instead", "2.10.0") type GenericClassManifestTraversableTemplate[+A, +CC[X] <: Traversable[X]] = GenericClassTagTraversableTemplate[A, CC] -} \ No newline at end of file +} diff --git a/test/files/run/enrich-gentraversable.check b/test/files/run/enrich-gentraversable.check index 348b38d6a4b5..94c66e36921d 100644 --- a/test/files/run/enrich-gentraversable.check +++ b/test/files/run/enrich-gentraversable.check @@ -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) diff --git a/test/files/run/enrich-gentraversable.scala b/test/files/run/enrich-gentraversable.scala index c9320ff985e3..52eded55fd89 100644 --- a/test/files/run/enrich-gentraversable.scala +++ b/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 }