diff --git a/src/main/scala/org/scalacheck/Arbitrary.scala b/src/main/scala/org/scalacheck/Arbitrary.scala index 15774a72b..63d2865d1 100644 --- a/src/main/scala/org/scalacheck/Arbitrary.scala +++ b/src/main/scala/org/scalacheck/Arbitrary.scala @@ -268,16 +268,18 @@ object Arbitrary { implicit def arbEither[T, U](implicit at: Arbitrary[T], au: Arbitrary[U]): Arbitrary[Either[T, U]] = Arbitrary(oneOf(arbitrary[T].map(Left(_)), arbitrary[U].map(Right(_)))) - /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container (such as lists, arrays, - * streams, etc). The maximum size of the container depends on the size - * generation parameter. */ - implicit def arbContainer[C[_],T](implicit a: Arbitrary[T], b: Buildable[T,C] + /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container + * (such as lists, arrays, streams, etc). The maximum size of the container + * depends on the size generation parameter. */ + implicit def arbContainer[C[_],T](implicit + a: Arbitrary[T], b: Buildable[T,C], t: C[T] => Traversable[T] ): Arbitrary[C[T]] = Arbitrary(containerOf[C,T](arbitrary[T])) - /** Arbitrary instance of any [[org.scalacheck.util.Buildable2]] container (such as maps, etc). - * The maximum size of the container depends on the size + /** Arbitrary instance of any [[org.scalacheck.util.Buildable2]] container + * (such as maps, etc). The maximum size of the container depends on the size * generation parameter. */ - implicit def arbContainer2[C[_,_],T,U](implicit a: Arbitrary[(T,U)], b: Buildable2[T,U,C] + implicit def arbContainer2[C[_,_],T,U](implicit + a: Arbitrary[(T,U)], b: Buildable2[T,U,C], t: C[T,U] => Traversable[(T,U)] ): Arbitrary[C[T,U]] = Arbitrary(containerOf[C,T,U](arbitrary[(T,U)])) // Functions // diff --git a/src/main/scala/org/scalacheck/Gen.scala b/src/main/scala/org/scalacheck/Gen.scala index 6eb155bb5..e660349cf 100644 --- a/src/main/scala/org/scalacheck/Gen.scala +++ b/src/main/scala/org/scalacheck/Gen.scala @@ -266,10 +266,7 @@ object Gen { case (rs,g) => g.doApply(p).flatMap(r => rs.map(_ :+ r)) } } - val sieve = gs.foldLeft((_:T) => false) { case (s,g) => - x:T => s(x) || g.sieveCopy(x) - } - g.map(b.fromIterable) // TODO .suchThat(_.forall(sieve)) + g.map(b.fromIterable) } /** Sequences generators. If any of the given generators fails, the @@ -280,10 +277,7 @@ object Gen { case (rs,g) => g.doApply(p).flatMap(r => rs.map(_ :+ r)) } } - val sieve = gs.foldLeft((_:T) => false) { case (s,g) => - x:T => s(x) || g.sieveCopy(x) - } - g.map(b.fromIterable) // TODO .suchThat(_.forall(sieve)) + g.map(b.fromIterable) } /** Wraps a generator lazily. The given parameter is only evaluated once, @@ -348,57 +342,84 @@ object Gen { //// List Generators //// - /** Generates a container of any type for which there exists an implicit + /** Generates a container of any Traversable type for which there exists an implicit * [[org.scalacheck.util.Buildable]] instance. The elements in the container will * be generated by the given generator. The size of the generated container * is given by `n`. If the given generator fails generating a value, the - * complete container gnerator will also fail. */ - def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit b: Buildable[T,C] - ): Gen[C[T]] = sequence[C,T](Traversable.fill(n)(g)) - - /** Generates a container of any type for which there exists an implicit - * [[org.scalacheck.util.Buildable]] instance. The elements in the container - * will be generated by the given generator. The size of the container is - * bounded by the size parameter used when generating values. */ - def containerOf[C[_],T](g: Gen[T])(implicit b: Buildable[T,C]): Gen[C[T]] = - sized(size => choose(0,size).flatMap(containerOfN[C,T](_,g))) + * complete container generator will also fail. */ + def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit + evb: Buildable[T,C], evt: C[T] => Traversable[T] + ): Gen[C[T]] = + sequence[C,T](Traversable.fill(n)(g)) suchThat { c => + c.size == n && c.forall(g.sieveCopy) + } - /** Generates a non-empty container of any type for which there exists an + /** Generates a container of any Traversable type for which there exists an * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the * container will be generated by the given generator. The size of the * container is bounded by the size parameter used when generating values. */ - def nonEmptyContainerOf[C[_],T](g: Gen[T])(implicit b: Buildable[T,C]): Gen[C[T]] = - sized(size => choose(1,size).flatMap(containerOfN[C,T](_,g))) + def containerOf[C[_],T](g: Gen[T])(implicit + evb: Buildable[T,C], evt: C[T] => Traversable[T] + ): Gen[C[T]] = + sized(s => choose(0,s).flatMap(containerOfN[C,T](_,g))) suchThat { c => + c.forall(g.sieveCopy) + } - /** Generates a non-empty container of any type for which there exists an - * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the - * container will be generated by the given generator. The size of the - * container is bounded by the size parameter used when generating values. */ - @deprecated("Use Gen.nonEmptyContainerOf instead", "1.11.0") - def containerOf1[C[_],T](g: Gen[T])(implicit b: Buildable[T,C]): Gen[C[T]] = - nonEmptyContainerOf[C,T](g) + /** Generates a non-empty container of any Traversable type for which there + * exists an implicit [[org.scalacheck.util.Buildable]] instance. The + * elements in the container will be generated by the given generator. The + * size of the container is bounded by the size parameter used when + * generating values. */ + def nonEmptyContainerOf[C[_],T](g: Gen[T])(implicit + evb: Buildable[T,C], evt: C[T] => Traversable[T] + ): Gen[C[T]] = + sized(s => choose(1,s).flatMap(containerOfN[C,T](_,g))) suchThat { c => + c.size > 0 && c.forall(g.sieveCopy) + } - /** Generates a container of any type for which there exists an implicit - * [[org.scalacheck.util.Buildable2]] instance. The elements in the container will - * be generated by the given generator. The size of the generated container - * is given by `n`. If the given generator fails generating a value, the - * complete container gnerator will also fail. */ - def containerOfN[C[_,_],T,U](n: Int, g: Gen[(T,U)])(implicit b: Buildable2[T,U,C] - ): Gen[C[T,U]] = sequence[C,T,U](Traversable.fill(n)(g)) + /** Generates a non-empty container of any Traversable type for which there + * exists an implicit [[org.scalacheck.util.Buildable]] instance. The + * elements in the container will be generated by the given generator. The + * size of the container is bounded by the size parameter used when + * generating values. */ + @deprecated("Use Gen.nonEmptyContainerOf instead", "1.11.0") + def containerOf1[C[_],T](g: Gen[T])(implicit + evb: Buildable[T,C], evt: C[T] => Traversable[T] + ): Gen[C[T]] = nonEmptyContainerOf[C,T](g) + + /** Generates a container of any Traversable type for which there exists an + * implicit [[org.scalacheck.util.Buildable2]] instance. The elements in + * the container will be generated by the given generator. The size of the + * generated container is given by `n`. If the given generator fails + * generating a value, the complete container generator will also fail. */ + def containerOfN[C[_,_],T,U](n: Int, g: Gen[(T,U)])(implicit + evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)] + ): Gen[C[T,U]] = + sequence[C,T,U](Traversable.fill(n)(g)).suchThat { c => + c.size == n && c.forall(g.sieveCopy) + } - /** Generates a container of any type for which there exists an implicit - * Buildable2 instance. The elements in the container will - * be generated by the given generator. The size of the container is - * bounded by the size parameter used when generating values. */ - def containerOf[C[_,_],T,U](g: Gen[(T,U)])(implicit b: Buildable2[T,U,C]): Gen[C[T,U]] = - sized(size => for(n <- choose(0,size); c <- containerOfN[C,T,U](n,g)) yield c) + /** Generates a container of any Traversable type for which there exists + * an implicit Buildable2 instance. The elements in the + * container will be generated by the given generator. The size of the + * container is bounded by the size parameter used when generating values. */ + def containerOf[C[_,_],T,U](g: Gen[(T,U)])(implicit + evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)] + ): Gen[C[T,U]] = + sized(s => choose(0,s).flatMap(containerOfN[C,T,U](_,g))) suchThat { c => + c.forall(g.sieveCopy) + } /** Generates a non-empty container of any type for which there exists an * implicit Buildable2 instance. The elements in the container * will be generated by the given generator. The size of the container is * bounded by the size parameter used when generating values. */ - def nonEmptyContainerOf[C[_,_],T,U](g: Gen[(T,U)])(implicit b: Buildable2[T,U,C]): Gen[C[T,U]] = - sized(size => for(n <- choose(1,size); c <- containerOfN[C,T,U](n,g)) yield c) + def nonEmptyContainerOf[C[_,_],T,U](g: Gen[(T,U)])(implicit + evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)] + ): Gen[C[T,U]] = + sized(s => choose(1,s).flatMap(containerOfN[C,T,U](_,g))) suchThat { c => + c.size > 0 && c.forall(g.sieveCopy) + } /** Generates a list of random length. The maximum length depends on the * size parameter. This method is equal to calling @@ -482,16 +503,18 @@ object Gen { /* Generates a string that starts with a lower-case alpha character, * and only contains alphanumerical characters */ - def identifier: Gen[String] = for { + def identifier: Gen[String] = (for { c <- alphaLowerChar cs <- listOf(alphaNumChar) - } yield (c::cs).mkString // TODO suchThat + } yield (c::cs).mkString).suchThat(_.forall(c => c.isLetter || c.isDigit)) /* Generates a string of alpha characters */ - def alphaStr: Gen[String] = listOf(alphaChar).map(_.mkString) // TODO suchThat + def alphaStr: Gen[String] = + listOf(alphaChar).map(_.mkString).suchThat(_.forall(_.isLetter)) /* Generates a string of digits */ - def numStr: Gen[String] = listOf(numChar).map(_.mkString) // TODO suchThat + def numStr: Gen[String] = + listOf(numChar).map(_.mkString).suchThat(_.forall(_.isDigit)) //// Number Generators //// diff --git a/src/main/scala/org/scalacheck/util/Buildable.scala b/src/main/scala/org/scalacheck/util/Buildable.scala index fac8b0a50..eb959ee6a 100644 --- a/src/main/scala/org/scalacheck/util/Buildable.scala +++ b/src/main/scala/org/scalacheck/util/Buildable.scala @@ -18,7 +18,6 @@ trait Buildable[T,C[_]] { b ++= it b.result() } - // TODO def toIterable } trait Buildable2[T,U,C[_,_]] { diff --git a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala index f44bf474e..4f23462e1 100644 --- a/src/test/scala/org/scalacheck/util/BuildableSpecification.scala +++ b/src/test/scala/org/scalacheck/util/BuildableSpecification.scala @@ -13,8 +13,10 @@ package util import collection._ object BuildableSpecification { - def container[C[_]](implicit ev: Buildable[String, C]) = - Gen.containerOf[C, String](Gen.alphaStr) + def container[C[_]](implicit + evb: Buildable[String, C], + evt: C[String] => Traversable[String] + ) = Gen.containerOf[C, String](Gen.alphaStr) implicit val listGen: Gen[List[String]] = container[List] @@ -41,4 +43,4 @@ object BuildableSpecification { implicit val iterableGen: Gen[immutable.Iterable[String]] = container[immutable.Iterable] implicit val trieIteratorGen: Gen[immutable.Queue[String]] = container[immutable.Queue] -} \ No newline at end of file +}