I'm learning scala by reading the code from ScalaCheck and find many combinators are suffixed by suchThat
. However, in many cases suchThat doesn't look quite necessary. I'm wondering why they are designed in this way. Here's some excerpted from GitHub:
Example 1.
/** Picks a random value from a list */
def oneOf[T](xs: Seq[T]): Gen[T] =
choose(0, xs.size-1).map(xs(_)).suchThat(xs.contains)
map
picks an element from xs and therefore xs.contains
seems redundant.
--
Example 2.
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)
}
Why is c.size == n
needed, given that a successful sequence
would return in the length of n?
--
Example 3.
/** Generates a string of alpha characters */
def alphaStr: Gen[String] =
listOf(alphaChar).map(_.mkString).suchThat(_.forall(_.isLetter))
Generated strings would consist of list of alphaChar
which is chosen from uppercase and lowercase letters. Why do we need a suchThat
to check isLetter again?
--
See https://github.com/rickynils/scalacheck/commit/2d92eb61a89a8ec2e16d0af8599f9baafc9b5418
Basically, this is needed for the ScalaCheck test case simplification to know what bounds the generated values originally had.