Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion test/shared/src/main/scala/zio/test/laws/GenF.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import zio.test.{ Gen, Sized }
* knows how to generate lists with elements given a generator of elements of
* that type. You can think of `GenF` as a "recipe" for building generators
* for parameterized types.
* `
*/
trait GenF[-R, F[_]] {

Expand Down
31 changes: 31 additions & 0 deletions test/shared/src/main/scala/zio/test/laws/GenF2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package zio.test.laws

import zio.random.Random
import zio.test.{ FunctionVariants, Gen }

/**
* A `GenF` knows how to construct a generator of `F[A,B]` values given a
* generator of `A` and generator of `B` values. For example, a `GenF2` of `Function1` values
* knows how to generate functions A => B with elements given a generator of elements of
* that type `B`.
*/
trait GenF2[-R, F[_, _]] {

/**
* Construct a generator of `F[A,B]` values given a generator of `B` values.
*/
def apply[R1 <: R, A, B](gen: Gen[R1, B]): Gen[R1, F[A, B]]
}

object GenF2 extends FunctionVariants {

/**
* A generator of `Function1` A => B values.
*/
val function1: GenF2[Random, Function1] =
new GenF2[Random, Function1] {

override def apply[R1 <: Random, A, B](gen: Gen[R1, B]): Gen[R1, Function1[A, B]] =
function[R1, A, B](gen)
}
}
1 change: 1 addition & 0 deletions test/shared/src/main/scala/zio/test/laws/ZLawful.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ package zio.test.laws
*/
trait ZLawful[-Caps[_], -R] { self =>
def laws: ZLaws[Caps, R]

def +[Caps1[x] <: Caps[x], R1 <: R](that: ZLawful[Caps1, R1]): ZLawful[Caps1, R1] =
new ZLawful[Caps1, R1] {
val laws = self.laws + that.laws
Expand Down
2 changes: 1 addition & 1 deletion test/shared/src/main/scala/zio/test/laws/ZLawfulF.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package zio.test.laws

/**
* `ZLawful[CapsF, Caps, R]` describes a set of laws that a parameterized type
* `ZLawfulF[CapsF, Caps, R]` describes a set of laws that a parameterized type
* `F[A]` with capabilities `CapsF` is expected to satisfy with respect to all
* types `A` that have capabilities `Caps`. Lawful instances can be combined
* using `+` to describe a set of capabilities and all of the laws that those
Expand Down
15 changes: 15 additions & 0 deletions test/shared/src/main/scala/zio/test/laws/ZLawfulF2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package zio.test.laws

object ZLawfulF2 {

trait Divariant[-CapsBoth[_[-_, +_]], -CapsLeft[_], -CapsRight[_], -R] { self =>
def laws: ZLawsF2.Divariant[CapsBoth, CapsLeft, CapsRight, R]

def +[CapsBoth1[x[-_, +_]] <: CapsBoth[x], CapsLeft1[x] <: CapsLeft[x], CapsRight1[x] <: CapsRight[x], R1 <: R](
that: Divariant[CapsBoth1, CapsLeft1, CapsRight1, R1]
): Divariant[CapsBoth1, CapsLeft1, CapsRight1, R1] =
new Divariant[CapsBoth1, CapsLeft1, CapsRight1, R1] {
val laws = self.laws + that.laws
}
}
}
90 changes: 90 additions & 0 deletions test/shared/src/main/scala/zio/test/laws/ZLawsF2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package zio.test.laws

import zio.{ URIO, ZIO }
import zio.test.{ check, Gen, TestConfig, TestResult }

object ZLawsF2 {

/**
* `ZLawsF2` for Divariant type constructors.
*/
abstract class Divariant[-CapsF[_[-_, +_]], -CapsLeft[_], -CapsRight[_], -R] { self =>

/**
* Test that values of type `F[+_,-_]` satisfy the laws using the specified
* function to construct a generator of `F[A,B]` values given a generator of
* `B` values.
*/
def run[R1 <: R with TestConfig, F[-_, +_]: CapsF, A: CapsLeft, B: CapsRight](
genF: GenF2[R1, F],
gen: Gen[R1, B]
): ZIO[R1, Nothing, TestResult]

/**
* Combine these laws with the specified laws to produce a set of laws that
* require both sets of laws to be satisfied.
*/
def +[CapsF1[x[-_, +_]] <: CapsF[x], CapsLeft1[x] <: CapsLeft[x], CapsRight1[x] <: CapsRight[x], R1 <: R](
that: Divariant[CapsF1, CapsLeft1, CapsRight1, R1]
): Divariant[CapsF1, CapsLeft1, CapsRight1, R1] =
Divariant.Both(self, that)
}

object Divariant {

private final case class Both[-CapsBothF[_[-_, +_]], -CapsLeft[_], -CapsRight[_], -R](
left: Divariant[CapsBothF, CapsLeft, CapsRight, R],
right: Divariant[CapsBothF, CapsLeft, CapsRight, R]
) extends Divariant[CapsBothF, CapsLeft, CapsRight, R] {

override final def run[R1 <: R with TestConfig, F[-_, +_]: CapsBothF, A: CapsLeft, B: CapsRight](
genF: GenF2[R1, F],
gen: Gen[R1, B]
): ZIO[R1, Nothing, TestResult] = {
val lhs: ZIO[R1, Nothing, TestResult] = left.run(genF, gen)
val rhs: ZIO[R1, Nothing, TestResult] = right.run(genF, gen)
lhs.zipWith(rhs)(_ && _)
}
}

/**
* Constructs a law from a pure function taking one parameterized value and
* two functions that can be composed.
*/
abstract class ComposeLaw[-CapsBothF[_[-_, +_]], -Caps[_]](label: String)
extends Divariant[CapsBothF, Caps, Caps, Any] {
self =>
def apply[F[-_, +_]: CapsBothF, A: Caps, B: Caps, A1: Caps, A2: Caps](
fa: F[A, B],
f: A => A1,
g: A1 => A2
): TestResult

final def run[R <: TestConfig, F[-_, +_]: CapsBothF, A: Caps, B: Caps, A1: Caps, A2: Caps](
genF: GenF2[R, F],
genB: Gen[R, B],
genA1: Gen[R, A1],
genA2: Gen[R, A2]
): URIO[R, TestResult] =
check(
genF[R, A, B](genB),
Gen.function[R, A, A1](genA1),
Gen.function[R, A1, A2](genA2)
)(apply(_, _, _).map(_.label(label)))
}

/**
* Constructs a law from a pure function taking a single parameter.
*/
abstract class Law1[-CapsBothF[_[-_, +_]], -CapsLeft[_], -CapsRight[_]](label: String)
extends Divariant[CapsBothF, CapsLeft, CapsRight, Any] { self =>
def apply[F[-_, +_]: CapsBothF, A: CapsLeft, B: CapsRight](fa: F[A, B]): TestResult

final def run[R <: TestConfig, F[-_, +_]: CapsBothF, A: CapsLeft, B: CapsRight](
genF: GenF2[R, F],
gen: Gen[R, B]
): URIO[R, TestResult] =
check(genF[R, A, B](gen))(apply(_).map(_.label(label)))
}
}
}
16 changes: 16 additions & 0 deletions test/shared/src/main/scala/zio/test/laws/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ package object laws {
type Invariant[-CapsF[_[_]], -Caps[_]] = ZLawfulF.Invariant[CapsF, Caps, Any]
}

object LawfulF2 {
type Divariant[-CapsBoth[_[-_, +_]], -CapsLeft[_], -CapsRight[_]] =
ZLawfulF2.Divariant[CapsBoth, CapsLeft, CapsRight, Any]
}

object Laws {
type Law1[-Caps[_]] = ZLaws.Law1[Caps]
type Law1M[-Caps[_]] = ZLaws.Law1M[Caps, Any]
Expand Down Expand Up @@ -129,6 +134,17 @@ package object laws {
}
}

object LawsF2 {
type Divariant[-CapsBoth[_[-_, +_]], -CapsLeft[_], -CapsRight[_]] =
ZLawsF2.Divariant[CapsBoth, CapsLeft, CapsRight, Any]

object Divariant {
type ComposeLaw[-CapsBothF[_[-_, +_]], -Caps[_]] = ZLawsF2.Divariant.ComposeLaw[CapsBothF, Caps]
type Law1[CapsBothF[_[-_, +_]], -CapsLeft[_], -CapsRight[_]] =
ZLawsF2.Divariant.Law1[CapsBothF, CapsLeft, CapsRight]
}
}

/**
* Checks that all values generated by a the specified generator satisfy the
* expected behavior of the lawful instance.
Expand Down