From 6cec86ba8fe6a6f103c92e1fc3eb56ee7d80b780 Mon Sep 17 00:00:00 2001 From: Mike Curry Date: Wed, 3 Feb 2016 00:19:00 +0000 Subject: [PATCH 1/3] Better arbitrary for Int => Boolean Default Int => Boolean in scalacheck just returns a function which always returns the same value (true or false). This means that operations like dropWhile are not tested accurately. --- core/src/main/scala/cats/data/Streaming.scala | 4 ++-- core/src/main/scala/cats/data/StreamingT.scala | 2 +- laws/src/main/scala/cats/laws/discipline/Arbitrary.scala | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/cats/data/Streaming.scala b/core/src/main/scala/cats/data/Streaming.scala index 2a58376e0b..640b6bca2d 100644 --- a/core/src/main/scala/cats/data/Streaming.scala +++ b/core/src/main/scala/cats/data/Streaming.scala @@ -524,7 +524,7 @@ sealed abstract class Streaming[A] extends Product with Serializable { lhs => * * For example: * - * Streaming(1, 2, 3, 4, 5, 6, 7).takeWhile(n => n != 4) + * Streaming(1, 2, 3, 4, 5, 6, 7).dropWhile(n => n != 4) * * Will result in: Streaming(4, 5, 6, 7) */ @@ -532,7 +532,7 @@ sealed abstract class Streaming[A] extends Product with Serializable { lhs => this match { case Empty() => Empty() case Wait(lt) => Wait(lt.map(_.dropWhile(f))) - case Cons(a, lt) => if (f(a)) Empty() else Cons(a, lt.map(_.dropWhile(f))) + case Cons(a, lt) => if (f(a)) Wait(lt.map(_.dropWhile(f))) else Cons(a, lt) } /** diff --git a/core/src/main/scala/cats/data/StreamingT.scala b/core/src/main/scala/cats/data/StreamingT.scala index 54f46eb1e2..1ae7150d8f 100644 --- a/core/src/main/scala/cats/data/StreamingT.scala +++ b/core/src/main/scala/cats/data/StreamingT.scala @@ -251,7 +251,7 @@ sealed abstract class StreamingT[F[_], A] extends Product with Serializable { lh */ def dropWhile(f: A => Boolean)(implicit ev: Functor[F]): StreamingT[F, A] = this match { - case Cons(a, ft) => if (f(a)) Empty() else Cons(a, ft.map(_.dropWhile(f))) + case Cons(a, ft) => if (f(a)) Wait(ft.map(_.dropWhile(f))) else Cons(a, ft) case Wait(ft) => Wait(ft.map(_.dropWhile(f))) case Empty() => Empty() } diff --git a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala index ec5da2481b..cb69e6964d 100644 --- a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala +++ b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala @@ -11,6 +11,12 @@ import org.scalacheck.Arbitrary.{arbitrary => getArbitrary} */ object arbitrary extends ArbitraryInstances0 { + // A special function1Arbitrary for testing operations like dropWhile specifically + // in the context of Int => Boolean. Once scalacheck supports better Function1 arbitrary + // instances this can be removed. + implicit def function1Arbitrary: Arbitrary[(Int) => Boolean] = + Arbitrary(getArbitrary[Int].map(x => (input) => input < x)) + implicit def constArbitrary[A, B](implicit A: Arbitrary[A]): Arbitrary[Const[A, B]] = Arbitrary(A.arbitrary.map(Const[A, B])) From 4e7002848e83086318a9e26255f0fb12b4160522 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Tue, 2 Feb 2016 22:23:28 -0500 Subject: [PATCH 2/3] Use sbt-doctest for some Streaming(T) examples --- core/src/main/scala/cats/data/Streaming.scala | 18 +++++++++-------- .../src/main/scala/cats/data/StreamingT.scala | 20 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/core/src/main/scala/cats/data/Streaming.scala b/core/src/main/scala/cats/data/Streaming.scala index 640b6bca2d..3106fbca92 100644 --- a/core/src/main/scala/cats/data/Streaming.scala +++ b/core/src/main/scala/cats/data/Streaming.scala @@ -501,10 +501,11 @@ sealed abstract class Streaming[A] extends Product with Serializable { lhs => * If no elements satisfy `f`, an empty stream will be returned. * * For example: - * - * Streaming(1, 2, 3, 4, 5, 6, 7).takeWhile(n => n != 4) - * - * Will result in: Streaming(1, 2, 3) + * {{{ + * scala> val s = Streaming(1, 2, 3, 4, 5, 6, 7) + * scala> s.takeWhile(n => n != 4).toList + * res0: List[Int] = List(1, 2, 3) + * }}} */ def takeWhile(f: A => Boolean): Streaming[A] = this match { @@ -523,10 +524,11 @@ sealed abstract class Streaming[A] extends Product with Serializable { lhs => * If no elements satisfy `f`, the current stream will be returned. * * For example: - * - * Streaming(1, 2, 3, 4, 5, 6, 7).dropWhile(n => n != 4) - * - * Will result in: Streaming(4, 5, 6, 7) + * {{{ + * scala> val s = Streaming(1, 2, 3, 4, 5, 6, 7) + * scala> s.dropWhile(n => n != 4).toList + * res0: List[Int] = List(4, 5, 6, 7) + * }}} */ def dropWhile(f: A => Boolean): Streaming[A] = this match { diff --git a/core/src/main/scala/cats/data/StreamingT.scala b/core/src/main/scala/cats/data/StreamingT.scala index 1ae7150d8f..8d368e0f38 100644 --- a/core/src/main/scala/cats/data/StreamingT.scala +++ b/core/src/main/scala/cats/data/StreamingT.scala @@ -222,10 +222,12 @@ sealed abstract class StreamingT[F[_], A] extends Product with Serializable { lh * If no elements satisfy `f`, an empty stream will be returned. * * For example: - * - * StreamingT[List, Int](1, 2, 3, 4, 5, 6, 7).takeWhile(n => n != 4) - * - * Will result in: StreamingT[List, Int](1, 2, 3) + * {{{ + * scala> import cats.std.list._ + * scala> val s = StreamingT[List, Int](1, 2, 3, 4, 5, 6, 7) + * scala> s.takeWhile(n => n != 4).toList.flatten + * res0: List[Int] = List(1, 2, 3) + * }}} */ def takeWhile(f: A => Boolean)(implicit ev: Functor[F]): StreamingT[F, A] = this match { @@ -244,10 +246,12 @@ sealed abstract class StreamingT[F[_], A] extends Product with Serializable { lh * If no elements satisfy `f`, the current stream will be returned. * * For example: - * - * StreamingT[List, Int](1, 2, 3, 4, 5, 6, 7).dropWhile(n => n != 4) - * - * Will result in: StreamingT[List, Int](4, 5, 6, 7) + * {{{ + * scala> import cats.std.list._ + * scala> val s = StreamingT[List, Int](1, 2, 3, 4, 5, 6, 7) + * scala> s.dropWhile(n => n != 4).toList.flatten + * res0: List[Int] = List(4, 5, 6, 7) + * }}} */ def dropWhile(f: A => Boolean)(implicit ev: Functor[F]): StreamingT[F, A] = this match { From e180959a22d67a27f97b1c34c8d87b3e996e701d Mon Sep 17 00:00:00 2001 From: Mike Curry Date: Wed, 3 Feb 2016 20:13:02 +0000 Subject: [PATCH 3/3] Remove a runtime Cons allocation. --- core/src/main/scala/cats/data/Streaming.scala | 2 +- core/src/main/scala/cats/data/StreamingT.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/data/Streaming.scala b/core/src/main/scala/cats/data/Streaming.scala index 3106fbca92..bb61a2e5a3 100644 --- a/core/src/main/scala/cats/data/Streaming.scala +++ b/core/src/main/scala/cats/data/Streaming.scala @@ -534,7 +534,7 @@ sealed abstract class Streaming[A] extends Product with Serializable { lhs => this match { case Empty() => Empty() case Wait(lt) => Wait(lt.map(_.dropWhile(f))) - case Cons(a, lt) => if (f(a)) Wait(lt.map(_.dropWhile(f))) else Cons(a, lt) + case s @ Cons(a, lt) => if (f(a)) Wait(lt.map(_.dropWhile(f))) else s } /** diff --git a/core/src/main/scala/cats/data/StreamingT.scala b/core/src/main/scala/cats/data/StreamingT.scala index 8d368e0f38..51c972f22e 100644 --- a/core/src/main/scala/cats/data/StreamingT.scala +++ b/core/src/main/scala/cats/data/StreamingT.scala @@ -255,7 +255,7 @@ sealed abstract class StreamingT[F[_], A] extends Product with Serializable { lh */ def dropWhile(f: A => Boolean)(implicit ev: Functor[F]): StreamingT[F, A] = this match { - case Cons(a, ft) => if (f(a)) Wait(ft.map(_.dropWhile(f))) else Cons(a, ft) + case s @ Cons(a, ft) => if (f(a)) Wait(ft.map(_.dropWhile(f))) else s case Wait(ft) => Wait(ft.map(_.dropWhile(f))) case Empty() => Empty() }