liveBook · Manning

Forall

As explained in Functional Programming in Scala, Second Edition

Prop.forAll is a ScalaCheck API function that constructs a property by applying a predicate to values generated by a Gen.

Prop.forAll turns a generator and a predicate into a property: `def forAll[A](a: Gen[A])(f: A => Boolean): Prop`. Rather than checking one hand-picked value, it states that every value supplied by `Gen[A]` should satisfy `A => Boolean`. The result is a `Prop`, not a Boolean, so it can be run later and combined with other properties. section 8.1 section 8.1.2

This separation matters because a generator describes how to obtain test data, while a property describes the test to perform. A list generator can produce lists of varying lengths and values; one predicate can assert that reversing twice returns the original list, while another relates `headOption` to the reversed list’s `lastOption`. Combining the resulting properties with `&&` forms a partial specification: both claims must resist falsification. section 8.1 section 8.1.2

Expressing laws over generated lists

```scala val intList = Gen.listOf(Gen.choose(0, 100)) val prop = Prop.forAll(intList)(ns => ns.reverse.reverse == ns) && Prop.forAll(intList)(ns => ns.headOption == ns.reverse.lastOption) val failingProp = Prop.forAll(intList)(ns => ns.reverse == ns) ``` The first two predicates express stable relationships rather than particular expected outputs. The last makes a deliberately false universal claim, so a test run can report a generated counterexample such as `List(0, 1)`. section 8.1

A useful `Prop` must preserve the outcome of testing instead of merely printing it. If checking returned `Unit`, combining two properties would only run two independent side effects and discard the information needed to control composition. Returning a result permits `&&` to stop on a failure and `||` to try its alternative after a failure; failures can retain both the failing case and the number of prior successes. section 8.1.3 section 8.6

To implement `forAll`, a property needs more than its generator and predicate at construction time. Running it requires a test-case count and a source of randomness. It repeatedly draws generated values, evaluates the predicate, returns `Passed` if none fail, and returns `Falsified` with diagnostic information at the first false result. Exceptions from the predicate are also converted into failures so the triggering input is retained. section 8.1.6

Listing 8.3 Implementing forAll
def forAll[A](as: Gen[A])(f: A => Boolean): Prop =
  (n, rng) =>
    randomLazyList(as)(rng)
      .zip(LazyList.from(0))
      .take(n)
      .map:                                                #1
        case (a, i) =>
          try
            if f(a) then Passed
            else Falsified(a.toString, i)                  #2
          catch
            case e: Exception =>
              Falsified(buildMsg(a, e), i)                 #3
      .find(_.isFalsified)
      .getOrElse(Passed)
}
 
def randomLazyList[A](g: Gen[A])(rng: RNG): LazyList[A] =
  LazyList.unfold(rng)(rng => Some(g.run(rng)))            #4
 
def buildMsg[A](s: A, e: Exception): String =
  s"test case: $s\n" +                                     #5
  s"generated an exception: ${e.getMessage}\n" +
  s"stack trace:\n ${e.getStackTrace.mkString("\n")}"

Inspect the complete loop: it creates a lazy stream of generated values, limits it to the requested test count, records the first falsification, and turns predicate exceptions into diagnostic failures. section 8.1.6

A later refinement distinguishes a property that is merely unfalsified from one proven over an exhaustively enumerated finite domain. `forAll` first consumes available exhaustive cases within its budget, then uses random samples when enumeration is incomplete. The result can therefore say whether all domain elements were checked or only whether no tested value falsified the predicate. section 8.6

When writing a property with `forAll`, make each part explicit:

  • Choose a `Gen[A]` that represents the inputs whose behavior is under test. section 8.1
  • Write an `A => Boolean` law that relates observable behavior instead of encoding a single example. section 8.1
  • Compose independent laws with `&&` when both must hold, and retain failure information for debugging. section 8.1.3 section 8.6

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Derives the polymorphic signature and implements execution with random inputs, result reporting, exceptions, and exhaustive-domain refinement.
Examples
Uses list reversal laws, Boolean properties, sorted lists, maximums, and a deliberately falsified reverse-equals-self claim.
What it assumes
Assumes Scala functions and `Gen[A]`, then derives `Prop` representation and property execution from the required behavior.
What you can do after
Build it from scratch as a generator-driven test loop that returns passing or falsified results with diagnostics.
How it connects
Connects generators, predicates, properties, logical combinators, random number generation, lazy lists, and exhaustive testing.

Also explained in

Compare how 2 books explain forall →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.