scalascalacheck

ScalaCheck generate a distinct list of values


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?


Solution

  • 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])