Skip to content

Commit

Permalink
Make Arbitrary Streaming instances more arbitrary
Browse files Browse the repository at this point in the history
This commit does two things.

1) Use a frequency distribution in the `StreamingT` generator as
suggested by @non [here](https://github.com/non/cats/pull/649#issuecomment-156856211).
It is now twice as likely to generate a Wait as an Empty and 6 times as
likely to generate a Cons as an Empty.
2) Update the `Streaming` generator to be similar to the `StreamingT`
generator (use a frequency distribution generator of Empty, Wait, and
Cons).
  • Loading branch information
ceedubs committed Nov 16, 2015
1 parent f4db3c4 commit c723afd
Showing 1 changed file with 31 additions and 16 deletions.
47 changes: 31 additions & 16 deletions laws/src/main/scala/cats/laws/discipline/Arbitrary.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,29 +53,44 @@ object arbitrary extends ArbitraryInstances0 {
implicit def appFuncArbitrary[F[_], A, B](implicit F: Arbitrary[F[B]], FF: Applicative[F]): Arbitrary[AppFunc[F, A, B]] =
Arbitrary(F.arbitrary.map(fb => Func.appFunc[F, A, B](_ => fb)))

implicit def streamingArbitrary[A](implicit A: Arbitrary[A]): Arbitrary[Streaming[A]] =
Arbitrary(Gen.listOf(A.arbitrary).map(Streaming.fromList(_)))
def streamingGen[A:Arbitrary](maxDepth: Int): Gen[Streaming[A]] =
if (maxDepth <= 1)
Gen.const(Streaming.empty[A])
else {
// the arbitrary instance for the next layer of the stream
implicit val A = Arbitrary(streamingGen[A](maxDepth - 1))
Gen.frequency(
// Empty
1 -> Gen.const(Streaming.empty[A]),
// Wait
2 -> getArbitrary[Eval[Streaming[A]]].map(Streaming.wait(_)),
// Cons
6 -> (for {
a <- getArbitrary[A]
tail <- getArbitrary[Eval[Streaming[A]]]
} yield Streaming.cons(a, tail)))
}

implicit def streamingArbitrary[A:Arbitrary]: Arbitrary[Streaming[A]] =
Arbitrary(streamingGen[A](8))

def emptyStreamingTGen[F[_], A]: Gen[StreamingT[F, A]] =
Gen.const(StreamingT.empty[F, A])

def streamingTGen[F[_], A](maxDepth: Int)(implicit F: Monad[F], A: Arbitrary[A]): Gen[StreamingT[F, A]] = {
if (maxDepth <= 1)
emptyStreamingTGen[F, A]
else {
Gen.oneOf(
// Empty
emptyStreamingTGen[F, A],
// Wait
streamingTGen[F, A](maxDepth - 1).map(s =>
StreamingT.wait(F.pure(s))),
// Cons
for {
a <- A.arbitrary
s <- streamingTGen[F, A](maxDepth - 1)
} yield StreamingT.cons(a, F.pure(s))
)
}
else Gen.frequency(
// Empty
1 -> emptyStreamingTGen[F, A],
// Wait
2 -> streamingTGen[F, A](maxDepth - 1).map(s =>
StreamingT.wait(F.pure(s))),
// Cons
6 -> (for {
a <- A.arbitrary
s <- streamingTGen[F, A](maxDepth - 1)
} yield StreamingT.cons(a, F.pure(s))))
}

// The max possible size of a StreamingT instance (n) will result in
Expand Down

0 comments on commit c723afd

Please sign in to comment.