I am fairly new to ScalaCheck and somehow I want to generate a list of distinct values (i.e. a set). With my approach the values are not unique.
val valueList: Gen[List[Int]] = Gen.ListOf(Arbitrary.arbitrary[Int])
What are the possible ways to create a list with unique values/a set? Maybe with using suchThat
or distinct
?
Crude but effective:
Gen.listOf(Arbitrary.arbitrary[Int]).map(_.toSet)
If you wanted a set of a particular size, you could do something like
def setOfN[A](n: Int, gen: Gen[A]): Gen[Set[A]] =
Gen.listOfN(n, gen).flatMap { lst =>
val set = lst.toSet
if (set.size == n) Gen.const(set)
else if (set.size > n) Gen.const(set.take(n))
else setOfN(n - set.size, gen.retryUntil(x => !set(x))).flatMap(_ ++ set)
}
(It's worth noting that retryUntil can be fragile, especially as n grows relative to the number of commonly generated values (e.g. for Int
Scalacheck generates 0, +/- 1, etc. fairly frequently))
And of course, since there's an org.scalacheck.util.Buildable
instance for Set
Gen.containerOf[Set, Int](Arbitrary.arbitrary[Int])