From c3409dc91215d1fd4fb72d3b7c5c774126c62c8d Mon Sep 17 00:00:00 2001 From: "Aaron S. Hawley" Date: Thu, 13 May 2021 00:23:54 -0400 Subject: [PATCH] Improve docs for Arbitrary --- src/main/scala/org/scalacheck/Arbitrary.scala | 89 ++++++++++++------- 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/src/main/scala/org/scalacheck/Arbitrary.scala b/src/main/scala/org/scalacheck/Arbitrary.scala index b8067766f..53c0d410d 100644 --- a/src/main/scala/org/scalacheck/Arbitrary.scala +++ b/src/main/scala/org/scalacheck/Arbitrary.scala @@ -17,48 +17,77 @@ import scala.concurrent.duration.{Duration, FiniteDuration} import util.Buildable import util.SerializableCanBuildFroms._ - -sealed abstract class Arbitrary[T] extends Serializable { - def arbitrary: Gen[T] -} - -/** Defines implicit [[org.scalacheck.Arbitrary]] instances for common types. - *

- * ScalaCheck - * uses implicit [[org.scalacheck.Arbitrary]] instances when creating properties - * out of functions with the `Prop.property` method, and when - * the `Arbitrary.arbitrary` method is used. For example, the - * following code requires that there exists an implicit - * `Arbitrary[MyClass]` instance: - *

+/** + * Define an arbitrary generator for properties + * + * The [[Arbitrary]] module defines implicit generator instances for + * common types. + * + * The implicit definitions of [[Arbitrary]] provide type-directed + * [[Gen]]s so they are available for properties, generators, or other + * definitions of [[Arbitrary]]. + * + * ScalaCheck expects an implicit [[Arbitrary]] instance is in scope + * for [[Prop]]s that are defined with functions, like [[Prop$.forAll[T1,P](g1* + * Prop.forAll]] and so on. + * + * For instance, the definition for `Arbitrary[Boolean]` is used by + * `Prop.forAll` to automatically provide a `Gen[Boolean]` when one + * of the parameters is a `Boolean`: * * {{{ - * val myProp = Prop.forAll { myClass: MyClass => - * ... + * Prop.forAll { (b: Boolean) => + * b || !b * } + * }}} * - * val myGen = Arbitrary.arbitrary[MyClass] + * Thanks to `Arbitrary`, you don't need to provide an explicit + * `Gen` instance to `Prop.forAll`. For instance, this is + * unnecessary: + * + * {{{ + * val genBool: Gen[Boolean] = Gen.oneOf(true,false) + * Prop.forAll(genBool) { (b: Boolean) => + * b || !b + * } * }}} * - *

- * The required implicit definition could look like this: - *

+ * Since an arbitrary `Gen` for `Boolean` is defined in `Arbitrary`, + * it can be summoned with `Arbitrary.arbitrary` in cases where you + * need to provide one explicitly: * * {{{ - * implicit val arbMyClass: Arbitrary[MyClass] = Arbitrary(...) + * val genBool: Gen[Boolean] = Arbitrary.arbitrary[Boolean] + * val genSmallInt: Gen[Int] = Gen.choose(0, 9) + * Prop.forAll(genBool, genSmallInt) { (b: Boolean, i: Int) => + * i < 10 && b || !b + * } * }}} * - *

- * The factory method `Arbitrary(...)` takes a generator of type - * `Gen[T]` and returns an instance of `Arbitrary[T]`. - *

+ * For a user-defined `MyClass`, writing the following requires that + * there exists an implicit `Arbitrary[MyClass]` instance: * - *

- * The `Arbitrary` module defines implicit [[org.scalacheck.Arbitrary]] - * instances for common types, for convenient use in your properties and - * generators. - *

+ * {{{ + * Prop.forAll { (myClass: MyClass) => + * ... + * } + * }}} + * + * The implicit definition of `Arbitrary[MyClass]` would look like: + * + * {{{ + * implicit val arbMyClass: Arbitrary[MyClass] = Arbitrary { + * ... + * } + * }}} + * + * The factory method `Arbitrary(...)` expects a generator of type + * `Gen[MyClass]` then it will return an instance of `Arbitrary[MyClass]`. */ +sealed abstract class Arbitrary[T] extends Serializable { + def arbitrary: Gen[T] +} + object Arbitrary extends ArbitraryLowPriority with ArbitraryArities with time.JavaTimeArbitrary { /** Arbitrary instance of the Function0 type. */