Skip to content

Commit

Permalink
Merge pull request #649 from ceedubs/arb-streamingt
Browse files Browse the repository at this point in the history
Make Arbitrary StreamingT more arbitrary
  • Loading branch information
stew committed Nov 15, 2015
2 parents d0f9dba + e46b2e1 commit 0ea6fe0
Showing 1 changed file with 23 additions and 13 deletions.
36 changes: 23 additions & 13 deletions laws/src/main/scala/cats/laws/discipline/Arbitrary.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,35 @@ object arbitrary extends ArbitraryInstances0 {
implicit def streamingArbitrary[A](implicit A: Arbitrary[A]): Arbitrary[Streaming[A]] =
Arbitrary(Gen.listOf(A.arbitrary).map(Streaming.fromList(_)))

// TODO: it would be better to do this recursively, i.e. more like:
//
// Gen.oneOf(
// for { a <- arbitrary[A]; s <- arbitrary[F[StreamingT[F, A]]] } yield cons(a, s),
// for { s <- arbitrary[F[StreamingT[F, A]]] } yield wait(s),
// const(StreamingT.empty[F, A]))
//
// However, getting this right with Scalacheck (and avoiding SOEs) is
// somewhat fiddly, so this will have to do for now.
//
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))
)
}
}

// The max possible size of a StreamingT instance (n) will result in
// instances of up to n^3 in length when testing flatMap
// composition. The current value (8) could result in streams of up
// to 512 elements in length. Thus, since F may not be stack-safe,
// we want to keep n relatively small.
implicit def streamingTArbitrary[F[_], A](implicit F: Monad[F], A: Arbitrary[A]): Arbitrary[StreamingT[F, A]] =
Arbitrary(for {
as <- Gen.listOf(A.arbitrary).map(_.take(8))
} yield StreamingT.fromList(as))
Arbitrary(streamingTGen[F, A](8))

implicit def writerArbitrary[L:Arbitrary, V:Arbitrary]: Arbitrary[Writer[L, V]] =
writerTArbitrary[Id, L, V]
Expand Down

0 comments on commit 0ea6fe0

Please sign in to comment.