From 8f2a51e3e2f66c9ef9ffd62e6b35280f2421bd40 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Wed, 25 Apr 2018 22:47:07 +0200 Subject: [PATCH 1/2] Arbitrary instances for NonEmpty Lists and Vectors --- .../eu/timepit/refined/scalacheck/all.scala | 1 + .../refined/scalacheck/collection.scala | 23 +++++++++++++++++-- .../timepit/refined/scalacheck/string.scala | 9 ++------ .../scalacheck/CollectionArbitrarySpec.scala | 7 +++++- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/all.scala b/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/all.scala index 4ce14cd58..d2bd42f3b 100644 --- a/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/all.scala +++ b/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/all.scala @@ -8,3 +8,4 @@ object all with RefTypeInstances with StringInstances with CollectionInstances + with CollectionInstancesBinCompat1 diff --git a/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/collection.scala b/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/collection.scala index 206513d78..05133c780 100644 --- a/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/collection.scala +++ b/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/collection.scala @@ -1,12 +1,12 @@ package eu.timepit.refined.scalacheck import eu.timepit.refined.api.{Refined, RefType} -import eu.timepit.refined.collection.Size +import eu.timepit.refined.collection.{NonEmpty, Size} import org.scalacheck.{Arbitrary, Gen} import org.scalacheck.util.Buildable /** Module that provides `Arbitrary` instances for collection predicates. */ -object collection extends CollectionInstances +object collection extends CollectionInstances with CollectionInstancesBinCompat1 trait CollectionInstances { @@ -36,3 +36,22 @@ trait CollectionInstances { Gen.buildableOfN[C, T](n.value, arbT.arbitrary) }) } + +trait CollectionInstancesBinCompat1 { + + implicit def listNonEmptyArbitrary[F[_, _]: RefType, T: Arbitrary] + : Arbitrary[F[List[T], NonEmpty]] = + buildableNonEmptyArbitrary[F, List[T], T] + + implicit def vectorNonEmptyArbitrary[F[_, _]: RefType, T: Arbitrary] + : Arbitrary[F[Vector[T], NonEmpty]] = + buildableNonEmptyArbitrary[F, Vector[T], T] + + private[scalacheck] def buildableNonEmptyArbitrary[F[_, _]: RefType, C, T]( + implicit + arbT: Arbitrary[T], + ev1: Buildable[T, C], + ev2: C => Traversable[T] + ): Arbitrary[F[C, NonEmpty]] = + arbitraryRefType(Gen.nonEmptyBuildableOf(arbT.arbitrary)) +} diff --git a/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/string.scala b/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/string.scala index afbe91dd3..c8b83ba2f 100644 --- a/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/string.scala +++ b/modules/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/string.scala @@ -28,13 +28,8 @@ trait StringInstances { implicit def nonEmptyStringArbitrary[F[_, _]]( implicit rt: RefType[F] - ): Arbitrary[F[String, NonEmpty]] = { - val nonEmptyStringGen = for { - s <- Arbitrary.arbString.arbitrary - c <- Arbitrary.arbChar.arbitrary - } yield s + c.toString - arbitraryRefType(nonEmptyStringGen) - } + ): Arbitrary[F[String, NonEmpty]] = + collection.buildableNonEmptyArbitrary[F, String, Char] implicit def stringSizeArbitrary[F[_, _]: RefType, P]( implicit diff --git a/modules/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/CollectionArbitrarySpec.scala b/modules/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/CollectionArbitrarySpec.scala index abe38ee22..a08c48881 100644 --- a/modules/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/CollectionArbitrarySpec.scala +++ b/modules/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/CollectionArbitrarySpec.scala @@ -2,7 +2,7 @@ package eu.timepit.refined.scalacheck import eu.timepit.refined.W import eu.timepit.refined.api.Refined -import eu.timepit.refined.collection.{MaxSize, Size} +import eu.timepit.refined.collection.{MaxSize, NonEmpty, Size} import eu.timepit.refined.numeric.Interval import eu.timepit.refined.scalacheck.collection._ import eu.timepit.refined.scalacheck.numeric._ @@ -17,9 +17,14 @@ class CollectionArbitrarySpec extends Properties("CollectionArbitrary") { property("List[String] Refined MaxSize[_13]") = checkArbitraryRefinedType[List[String] Refined MaxSize[_13]] + property("List[Int] Refined NonEmpty") = checkArbitraryRefinedType[List[Int] Refined NonEmpty] + property("Vector[Int] Refined MaxSize[23]") = checkArbitraryRefinedType[Vector[Int] Refined MaxSize[W.`23`.T]] + property("Vector[Double] Refined NonEmpty") = + checkArbitraryRefinedType[Vector[Double] Refined NonEmpty] + property("Size[Interval.Closed[23, 42]]") = checkArbitraryRefinedType[List[Char] Refined Size[Interval.Closed[W.`23`.T, W.`42`.T]]] } From 05b311685e0bdcf6ec7a636ed6f8442c638fbb09 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Fri, 27 Apr 2018 20:32:40 +0200 Subject: [PATCH 2/2] Add release notes --- notes/0.9.1.markdown | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 notes/0.9.1.markdown diff --git a/notes/0.9.1.markdown b/notes/0.9.1.markdown new file mode 100644 index 000000000..75113cf2f --- /dev/null +++ b/notes/0.9.1.markdown @@ -0,0 +1,8 @@ +### New features + +* Add `Arbitrary` instances for `NonEmpty` `List`s and `Vector`s. + ([#486][#486] by [@fthomas][@fthomas]) + +[#486]: https://github.com/fthomas/refined/pull/486 + +[@fthomas]: https://github.com/fthomas