Skip to content

Commit f6ee4d4

Browse files
committed
Remove FromIterable upper bound, add BuildConstrained
1 parent d039e7f commit f6ee4d4

File tree

13 files changed

+64
-48
lines changed

13 files changed

+64
-48
lines changed

src/main/scala/strawman/collection/Iterable.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ trait Iterable[+A] extends IterableOnce[A] with IterableLike[A, Iterable] {
2727
*
2828
*/
2929
trait IterableLike[+A, +C[X] <: Iterable[X]]
30-
extends FromIterable[Any, C]
30+
extends FromIterable[C]
3131
with IterableOps[A]
3232
with IterableMonoTransforms[A, C[A @uncheckedVariance]] // sound bcs of VarianceNote
3333
with IterablePolyTransforms[A, C] {
@@ -88,11 +88,14 @@ trait IterableOps[+A] extends Any {
8888
* xs.to(ArrayBuffer)
8989
* xs.to(BitSet) // for xs: Iterable[Int]
9090
*/
91-
def to[F <: FromIterableBase[A]](fi: F): F#To[A @uncheckedVariance] =
91+
def to[F <: Build[A]](fi: F): fi.To[A @uncheckedVariance] =
9292
// variance seems sound because `to` could just as well have been added
9393
// as a decorator. We should investigate this further to be sure.
9494
fi.fromIterable(coll)
9595

96+
def to[F <: BuildConstrained](fi: F)(implicit c: fi.Constraint[A @uncheckedVariance]): c.To[A @uncheckedVariance] =
97+
c.fromIterable(coll)
98+
9699
def to[C[_], Ev[_]](fi: ConstrainedFromIterable[C, Ev])(implicit ev: Ev[A @uncheckedVariance]): C[A @uncheckedVariance] =
97100
fi.constrainedFromIterable(coll)
98101

src/main/scala/strawman/collection/IterableFactories.scala

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,23 @@ package collection
33

44
import strawman.collection.mutable.Builder
55

6-
import scala.Int
6+
import scala.{Any, Int}
77
import scala.annotation.unchecked.uncheckedVariance
88

9-
trait FromIterableBase[-B] {
10-
type To[X]
9+
/** Instances of Build[B] can build some kind of collection from values of type B. */
10+
trait Build[-B] {
11+
type To[_]
1112
def fromIterable[E <: B](it: Iterable[E]): To[E]
1213
}
1314

15+
trait BuildConstrained {
16+
trait Constraint[E] extends Build[E]
17+
}
18+
1419
/** Base trait for instances that can construct a collection from an iterable */
15-
trait FromIterable[-B, +C[_]] extends FromIterableBase[B] {
20+
trait FromIterable[+C[_]] extends Build[Any] {
1621
type To[X] = C[X] @uncheckedVariance
17-
def fromIterable[E <: B](it: Iterable[E]): C[E]
22+
def fromIterable[E](it: Iterable[E]): C[E]
1823
}
1924

2025
/** Base trait for instances that can construct a collection from an iterable by using an implicit evidence
@@ -23,28 +28,28 @@ trait ConstrainedFromIterable[+CC[_], Ev[_]] {
2328
def constrainedFromIterable[E : Ev](it: Iterable[E]): CC[E]
2429
}
2530

26-
/** Base trait for companion objects of collections */
27-
trait IterableFactory[-B, +C[_]] extends FromIterable[B, C] { self =>
31+
/** Base trait for companion objects of unconstrained collection types */
32+
trait IterableFactory[+C[_]] extends FromIterable[C] { self =>
33+
def empty[A]: C[A] = fromIterable(View.Empty)
2834

29-
def empty[A <: B]: C[A] = fromIterable(View.Empty)
35+
def apply[A](xs: A*): C[A] = fromIterable(View.Elems(xs: _*))
3036

31-
def apply[A <: B](xs: A*): C[A] = fromIterable(View.Elems(xs: _*))
37+
def fill[A](n: Int)(elem: => A): C[A] = fromIterable(View.Fill(n)(elem))
3238

33-
def fill[A <: B](n: Int)(elem: => A): C[A] = fromIterable(View.Fill(n)(elem))
39+
def newBuilder[A]: Builder[A, C[A]]
3440

35-
def newBuilder[A <: B]: Builder[A, C[A]]
36-
37-
protected[this] lazy val monomorphicIterableFactoryProto: MonomorphicIterableFactory[B, C[B]] = new MonomorphicIterableFactory[B, C[B]] {
38-
def fromIterable[E <: B](it: Iterable[E]): C[B] = self.fromIterable[B](it)
39-
def newBuilder[A <: B]: Builder[A, C[B]] = self.newBuilder[B]
40-
override protected[this] lazy val monomorphicIterableFactoryProto = this
41+
protected[this] lazy val canBuildProto: CanBuild[Any, C[Any]] = new CanBuild[Any, C[Any]] {
42+
def fromIterable(it: Iterable[Any]): C[Any] = self.fromIterable[Any](it)
43+
def newBuilder: Builder[Any, C[Any]] = self.newBuilder[Any]
4144
}
4245

43-
implicit def iterableFactory[E <: B]: MonomorphicIterableFactory[E, C[E]] =
44-
monomorphicIterableFactoryProto.asInstanceOf[MonomorphicIterableFactory[E, C[E]]]
46+
implicit def canBuild[E]: CanBuild[E, C[E]] = canBuildProto.asInstanceOf[CanBuild[E, C[E]]]
4547
}
4648

47-
trait MonomorphicIterableFactory[-B, +Repr] extends IterableFactory[B, ({ type L[X] = Repr })#L]
49+
trait CanBuild[E, +Repr] {
50+
def fromIterable(it: Iterable[E]): Repr
51+
def newBuilder: Builder[E, Repr]
52+
}
4853

4954
/** Base trait for companion objects of collections that require an implicit evidence */
5055
trait ConstrainedIterableFactory[+CC[X], Ev[_]] extends ConstrainedFromIterable[CC, Ev] {
@@ -57,8 +62,8 @@ trait ConstrainedIterableFactory[+CC[X], Ev[_]] extends ConstrainedFromIterable[
5762

5863
def constrainedNewBuilder[A : Ev]: Builder[A, CC[A]]
5964

60-
implicit def iterableFactory[B : Ev]: MonomorphicIterableFactory[B, CC[B]] = new MonomorphicIterableFactory[B, CC[B]] {
61-
def fromIterable[E <: B](it: Iterable[E]): CC[B] = constrainedFromIterable[B](it)
62-
def newBuilder[A <: B]: Builder[A, CC[B]] = constrainedNewBuilder[B]
65+
implicit def canBuild[E : Ev]: CanBuild[E, CC[E]] = new CanBuild[E, CC[E]] {
66+
def fromIterable(it: Iterable[E]): CC[E] = constrainedFromIterable[E](it)
67+
def newBuilder: Builder[E, CC[E]] = constrainedNewBuilder[E]
6368
}
6469
}

src/main/scala/strawman/collection/Map.scala

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ trait MapPolyTransforms[K, +V, +C[X, Y] <: Map[X, Y]] extends IterablePolyTransf
3131
}
3232

3333
/** Factory methods for collections of kind `* −> * -> *` */
34-
trait MapFactory[+C[_, _]] { self =>
34+
trait MapFactory[+C[_, _]] extends BuildConstrained { self =>
35+
class ConstraintImpl[E, Repr] extends Constraint[E] {
36+
type To[_] = Repr
37+
def fromIterable[X <: E](it: Iterable[X]): Repr = ???
38+
}
39+
implicit def constraint[K, V]: ConstraintImpl[(K, V), C[K, V] @uncheckedVariance] = new ConstraintImpl[(K, V), C[K, V] @uncheckedVariance]
3540

3641
def newBuilder[K, V]: Builder[(K, V), C[K, V]]
3742

@@ -44,14 +49,13 @@ trait MapFactory[+C[_, _]] { self =>
4449
def apply[K, V](elems: (K, V)*): C[K, V] =
4550
newBuilder[K, V].++=(elems.toStrawman).result
4651

47-
protected[this] lazy val monomorphicIterableFactoryProto: MonomorphicIterableFactory[(Any, Any), C[Any, Any]] = new MonomorphicIterableFactory[(Any, Any), C[Any, Any]] {
48-
def fromIterable[E](it: Iterable[E]): C[Any, Any] = self.fromIterable[Any, Any](it.asInstanceOf[Iterable[(Any, Any)]])
49-
def newBuilder[A]: Builder[A, C[Any, Any]] = self.newBuilder[Any, Any].asInstanceOf[Builder[A, C[Any, Any]]]
50-
override protected[this] lazy val monomorphicIterableFactoryProto = this
52+
protected[this] lazy val canBuildProto: CanBuild[(Any, Any), C[Any, Any]] = new CanBuild[(Any, Any), C[Any, Any]] {
53+
def fromIterable(it: Iterable[(Any, Any)]): C[Any, Any] = self.fromIterable[Any, Any](it)
54+
def newBuilder: Builder[(Any, Any), C[Any, Any]] = self.newBuilder[Any, Any]
5155
}
5256

53-
implicit def iterableFactory[K, V]: MonomorphicIterableFactory[(K, V), C[K, V]] =
54-
monomorphicIterableFactoryProto.asInstanceOf[MonomorphicIterableFactory[(K, V), C[K, V]]]
57+
implicit def canBuild[K, V]: CanBuild[(K, V), C[K, V]] =
58+
canBuildProto.asInstanceOf[CanBuild[(K, V), C[K, V]]]
5559
}
5660

5761
/** Factory methods for collections of kind `* −> * -> *` which require an implicit evidence value for the key type */
@@ -68,8 +72,8 @@ trait ConstrainedMapFactory[+C[_, _], Ev[_]] { self =>
6872
def apply[K : Ev, V](elems: (K, V)*): C[K, V] =
6973
constrainedNewBuilder[K, V].++=(elems.toStrawman).result
7074

71-
implicit def iterableFactory[K : Ev, V]: MonomorphicIterableFactory[(K, V), C[K, V]] = new MonomorphicIterableFactory[(K, V), C[K, V]] {
72-
def fromIterable[E <: (K, V)](it: Iterable[E]): C[K, V] = self.constrainedFromIterable(it)
73-
def newBuilder[A <: (K, V)]: Builder[A, C[K, V]] = self.constrainedNewBuilder
75+
implicit def canBuild[K : Ev, V]: CanBuild[(K, V), C[K, V]] = new CanBuild[(K, V), C[K, V]] {
76+
def fromIterable(it: Iterable[(K, V)]): C[K, V] = self.constrainedFromIterable(it)
77+
def newBuilder: Builder[(K, V), C[K, V]] = self.constrainedNewBuilder
7478
}
7579
}

src/main/scala/strawman/collection/immutable/BitSet.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package strawman
22
package collection.immutable
33

4-
import strawman.collection.MonomorphicIterableFactory
4+
import strawman.collection.Build
55
import strawman.collection.mutable.Builder
66

77
import scala.Int
@@ -13,9 +13,10 @@ trait BitSet
1313
with SortedSet[Int]
1414
with SetMonoTransforms[Int, BitSet] // Override mono transforms ops to return a BitSet rather than a SortedSet[Int]
1515

16-
object BitSet extends MonomorphicIterableFactory[Int, BitSet] {
16+
object BitSet extends Build[Int] {
17+
type To[_] = BitSet
1718

1819
def fromIterable[E <: Int](it: strawman.collection.Iterable[E]): BitSet = ???
1920

20-
def newBuilder[A <: Int]: Builder[A, BitSet] = ???
21+
def newBuilder[E <: Int]: Builder[E, BitSet] = ???
2122
}

src/main/scala/strawman/collection/immutable/HashSet.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class HashSet[A] extends Set[A] with SetLike[A, HashSet] {
3232

3333
}
3434

35-
object HashSet extends IterableFactory[Any, HashSet] {
35+
object HashSet extends IterableFactory[HashSet] {
3636

3737
def fromIterable[A](it: collection.Iterable[A]): HashSet[A] = ???
3838

src/main/scala/strawman/collection/immutable/LazyList.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class LazyList[+A](expr: => LazyList.Evaluated[A])
3939
else "LazyList(?)"
4040
}
4141

42-
object LazyList extends IterableFactory[Any, LazyList] {
42+
object LazyList extends IterableFactory[LazyList] {
4343

4444
type Evaluated[+A] = Option[(A, LazyList[A])]
4545

src/main/scala/strawman/collection/immutable/List.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ case object Nil extends List[Nothing] {
5151
override def tail = ???
5252
}
5353

54-
object List extends IterableFactory[Any, List] {
54+
object List extends IterableFactory[List] {
5555

5656
def fromIterable[B](coll: collection.Iterable[B]): List[B] = coll match {
5757
case coll: List[B] => coll

src/main/scala/strawman/collection/mutable/ArrayBuffer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class ArrayBuffer[A] private (initElems: Array[AnyRef], initLength: Int)
124124
override def className = "ArrayBuffer"
125125
}
126126

127-
object ArrayBuffer extends IterableFactory[Any, ArrayBuffer] {
127+
object ArrayBuffer extends IterableFactory[ArrayBuffer] {
128128

129129
/** Avoid reallocation of buffer if length is known. */
130130
def fromIterable[B](coll: collection.Iterable[B]): ArrayBuffer[B] =
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package strawman
22
package collection.mutable
33

4-
import strawman.collection.MonomorphicIterableFactory
4+
import strawman.collection.Build
55

66
import scala.Int
77
import scala.Predef.???
@@ -11,9 +11,10 @@ trait BitSet
1111
with collection.BitSetLike[BitSet]
1212
with SortedSet[Int]
1313

14-
object BitSet extends MonomorphicIterableFactory[Int, BitSet] {
14+
object BitSet extends Build[Int] {
15+
type To[_] = BitSet
1516

1617
def fromIterable[E <: Int](it: strawman.collection.Iterable[E]): BitSet = ???
1718

18-
def newBuilder[A <: Int]: Builder[A, BitSet] = ???
19+
def newBuilder[E <: Int]: Builder[E, BitSet] = ???
1920
}

src/main/scala/strawman/collection/mutable/HashSet.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ final class HashSet[A]
3333

3434
}
3535

36-
object HashSet extends IterableFactory[Any, HashSet] {
36+
object HashSet extends IterableFactory[HashSet] {
3737

3838
def fromIterable[B](it: strawman.collection.Iterable[B]): HashSet[B] = {
3939
val result = new HashSet[B]

src/main/scala/strawman/collection/mutable/ListBuffer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ class ListBuffer[A]
197197
override def className = "ListBuffer"
198198
}
199199

200-
object ListBuffer extends IterableFactory[Any, ListBuffer] {
200+
object ListBuffer extends IterableFactory[ListBuffer] {
201201

202202
def fromIterable[A](coll: collection.Iterable[A]): ListBuffer[A] = new ListBuffer[A] ++= coll
203203

src/test/scala/strawman/collection/test/Test.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,8 @@ class StrawmanTest {
336336
// val xs7 = xs.map((k: String, v: Int) => (new Foo, v)) Error: No implicit Ordering defined for Foo
337337
val xs7 = (xs: immutable.Map[String, Int]).map((k, v) => (new Foo, v))
338338
val xs8: immutable.Map[Foo, Int] = xs7
339+
val xs9 = xs6.to(List).to(mutable.HashMap)
340+
val xs9t: mutable.HashMap[Int, String] = xs9
339341
}
340342

341343
def bitSets(xs: immutable.BitSet, ys: BitSet, zs: Set[Int]): Unit = {

src/test/scala/strawman/collection/test/TraverseTest.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ import java.lang.String
1313

1414
class TraverseTest {
1515

16-
def optionSequence[C[X] <: Iterable[X], A](xs: C[Option[A]])(implicit fi: MonomorphicIterableFactory[A, C[A]]): Option[C[A]] =
16+
def optionSequence[C[X] <: Iterable[X], A](xs: C[Option[A]])(implicit fi: CanBuild[A, C[A]]): Option[C[A]] =
1717
xs.foldLeft[Option[Builder[A, C[A]]]](Some(fi.newBuilder)) {
1818
case (Some(builder), Some(a)) => Some(builder += a)
1919
case _ => None
2020
}.map(_.result)
2121

22-
def eitherSequence[C[X] <: Iterable[X], A, B](xs: C[Either[A, B]])(implicit fi: MonomorphicIterableFactory[B, C[B]]): Either[A, C[B]] =
22+
def eitherSequence[C[X] <: Iterable[X], A, B](xs: C[Either[A, B]])(implicit fi: CanBuild[B, C[B]]): Either[A, C[B]] =
2323
xs.foldLeft[Either[A, Builder[B, C[B]]]](Right(fi.newBuilder)) {
2424
case (Right(builder), Right(b)) => Right(builder += b)
2525
case (Left(a) , _) => Left(a)

0 commit comments

Comments
 (0)