package laws
The laws
package provides functionality for describing laws as values. The
fundamental abstraction is a set of ZLaws[Caps, R]
. These laws model the
laws that instances having a capability of type Caps
are expected to
satisfy. A capability Caps[_]
is an abstraction describing some
functionality that is common across different data types and obeys certain
laws. For example, we can model the capability of two values of a type being
compared for equality as follows:
trait Equal[-A] { def equal(a1: A, a2: A): Boolean }
Definitions of equality are expected to obey certain laws:
- Reflexivity -
a1 === a1
- Symmetry -
a1 === a2 ==> a2 === a1
- Transitivity -
(a1 === a2) && (a2 === a3) ==> (a1 === a3)
These laws define what the capabilities mean and ensure that it is safe to abstract across different instances with the same capability.
Using ZIO Test, we can represent these laws as values. To do so, we define
each law using one of the ZLaws
constructors. For example:
val transitivityLaw = ZLaws.Laws3[Equal]("transitivityLaw") { def apply[A: Equal](a1: A, a2: A, a3: A): TestResult = ??? }
We can then combine laws using the +
operator:
val reflexivityLaw: = ??? val symmetryLaw: = ??? val equalLaws = reflexivityLaw + symmetryLaw + transitivityLaw
Laws have a run
method that takes a generator of values of type A
and
checks that those values satisfy the laws. In addition, objects can extend
ZLawful
to provide an even more convenient syntax for users to check that
instances satisfy certain laws.
object Equal extends Lawful[Equal] object Hash extends Lawful[Hash] object Ord extends Lawful[Ord] checkAllLaws(Equal + Hash + Ord)(Gen.int)
Note that capabilities compose seamlessly because of contravariance. We can combine laws describing different capabilities to construct a set of laws requiring that instances having all of the capabilities satisfy each of the laws.
- Alphabetic
- By Inheritance
- laws
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Type Members
- trait GenF[-R, F[_]] extends AnyRef
A
GenF
knows how to construct a generator ofF[A]
values given a generator ofA
values for anyA
.A
GenF
knows how to construct a generator ofF[A]
values given a generator ofA
values for anyA
. For example, aGenF
ofList
values knows how to generate lists with elements given a generator of elements of that type. You can think ofGenF
as a "recipe" for building generators for parameterized types. - trait GenF2[-R, F[_, _]] extends AnyRef
A
GenF
knows how to construct a generator ofF[A,B]
values given a generator ofA
and generator ofB
values.A
GenF
knows how to construct a generator ofF[A,B]
values given a generator ofA
and generator ofB
values. For example, aGenF2
ofFunction1
values knows how to generate functions A => B with elements given a generator of elements of that typeB
. - type Lawful[-Caps[_]] = ZLawful[Caps, Any]
- type Lawful2[-CapsBoth[_, _], -CapsLeft[_], -CapsRight[_]] = ZLawful2[CapsBoth, CapsLeft, CapsRight, Any]
- type Laws[-Caps[_]] = ZLaws[Caps, Any]
- type Laws2[-CapsBoth[_, _], -CapsLeft[_], -CapsRight[_]] = ZLaws2[CapsBoth, CapsLeft, CapsRight, Any]
- trait ZLawful[-Caps[_], -R] extends AnyRef
ZLawful[Caps, R]
describes a capability that is expected to satisfy a set of laws.ZLawful[Caps, R]
describes a capability that is expected to satisfy a set of laws. Lawful instances can be combined using+
to describe a set of capabilities and all of the laws that those capabilities are expected to satisfy.trait Equal[-A] { def equal(a1: A, a2: A): Boolean } object Equal extends Lawful[Equal] { val laws = ??? }
- trait ZLawful2[-CapsBoth[_, _], -CapsLeft[_], -CapsRight[_], -R] extends AnyRef
- abstract class ZLaws[-Caps[_], -R] extends AnyRef
ZLaws[Caps, R]
represents a set of laws that values with capabilitiesCaps
are expected to satisfy.ZLaws[Caps, R]
represents a set of laws that values with capabilitiesCaps
are expected to satisfy. Laws can be run by providing a generator of values of a typeA
with the required capabilities to return a test result. Laws can be combined using+
to produce a set of laws that require both sets of laws to be satisfied. - abstract class ZLaws2[-CapsBoth[_, _], -CapsLeft[_], -CapsRight[_], -R] extends AnyRef
Value Members
- def checkAllLaws[CapsF[_[_]], Caps[_], R <: TestConfig, R1 <: R, F[_], A](lawful: Invariant[CapsF, Caps, R])(genF: GenF[R1, F], gen: Gen[R1, A])(implicit arg0: CapsF[F], arg1: Caps[A], trace: ZTraceElement): ZIO[R1, Nothing, TestResult]
Checks that all values generated by a the specified generator satisfy the expected behavior of the lawful instance.
- def checkAllLaws[CapsF[_[-_]], Caps[_], R <: TestConfig, R1 <: R, F[-_], A](lawful: Contravariant[CapsF, Caps, R])(genF: GenF[R1, F], gen: Gen[R1, A])(implicit arg0: CapsF[F], arg1: Caps[A], trace: ZTraceElement): ZIO[R1, Nothing, TestResult]
Checks that all values generated by a the specified generator satisfy the expected behavior of the lawful instance.
- def checkAllLaws[CapsF[_[+_]], Caps[_], R <: TestConfig, R1 <: R, F[+_], A](lawful: Covariant[CapsF, Caps, R])(genF: GenF[R1, F], gen: Gen[R1, A])(implicit arg0: CapsF[F], arg1: Caps[A], trace: ZTraceElement): ZIO[R1, Nothing, TestResult]
- def checkAllLaws[CapsBoth[_, _], CapsLeft[_], CapsRight[_], R <: TestConfig, R1 <: R, A, B](lawful: ZLawful2[CapsBoth, CapsLeft, CapsRight, R])(a: Gen[R1, A], b: Gen[R1, B])(implicit arg0: CapsLeft[A], arg1: CapsRight[B], CapsBoth: CapsBoth[A, B], trace: ZTraceElement): ZIO[R1, Nothing, TestResult]
Checks that all values generated by a the specified generator satisfy the expected behavior of the lawful instance.
- def checkAllLaws[Caps[_], R <: TestConfig, R1 <: R, A](lawful: ZLawful[Caps, R])(gen: Gen[R1, A])(implicit arg0: Caps[A], trace: ZTraceElement): ZIO[R1, Nothing, TestResult]
Checks that all values generated by a the specified generator satisfy the expected behavior of the lawful instance.
- object GenF
- object GenF2 extends FunctionVariants
- object LawfulF
- object LawfulF2
- object Laws
- object Laws2
- object LawsF
- object LawsF2
- object ZLawfulF
ZLawfulF[CapsF, Caps, R]
describes a set of laws that a parameterized typeF[A]
with capabilitiesCapsF
is expected to satisfy with respect to all typesA
that have capabilitiesCaps
.ZLawfulF[CapsF, Caps, R]
describes a set of laws that a parameterized typeF[A]
with capabilitiesCapsF
is expected to satisfy with respect to all typesA
that have capabilitiesCaps
. Lawful instances can be combined using+
to describe a set of capabilities and all of the laws that those capabilities are expected to satisfy. - object ZLawfulF2
- object ZLaws
- object ZLaws2
- object ZLawsF
ZLaws[CapsF, Caps, R]
describes a set of laws that a parameterized typeF[A]
with capabilitiesCapsF
is expected to satisfy with respect to all typesA
that have capabilitiesCaps
.ZLaws[CapsF, Caps, R]
describes a set of laws that a parameterized typeF[A]
with capabilitiesCapsF
is expected to satisfy with respect to all typesA
that have capabilitiesCaps
. Laws can be run by providing aGenF
that is capable of generatingF[A]
values given a generator ofA
values and a generator of values of some typeA
. Laws can be combined using+
to produce a set of laws that require both sets of laws to be satisfied. - object ZLawsF2