diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/BaseLaws.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/BaseLaws.scala deleted file mode 100644 index 4ac3c7bd79..0000000000 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/BaseLaws.scala +++ /dev/null @@ -1,28 +0,0 @@ -package cats.algebra.laws - -import cats.kernel._ - -import org.typelevel.discipline.Laws - -import org.scalacheck.{Arbitrary, Prop} - -object BaseLaws { - def apply[A: Eq: Arbitrary]: BaseLaws[A] = new BaseLaws[A] { - def Equ = Eq[A] - def Arb = implicitly[Arbitrary[A]] - } -} - -trait BaseLaws[A] extends Laws { - - implicit def Equ: Eq[A] - implicit def Arb: Arbitrary[A] - - class BaseRuleSet( - val name: String, - val parent: Option[RuleSet], - val bases: Seq[(String, Laws#RuleSet)], - val props: (String, Prop)* - ) extends RuleSet - with HasOneParent -} diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/CheckSupport.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/CheckSupport.scala deleted file mode 100644 index 41d0a2dc57..0000000000 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/CheckSupport.scala +++ /dev/null @@ -1,11 +0,0 @@ -package cats.algebra.laws - -/** - * This object contains Arbitrary instances for types defined in - * algebra.instances, as well as anything else we'd like to import to assist - * in running ScalaCheck tests. - * - * (Since algebra-instances has no dependencies, its types can't - * define Arbitrary instances in companions.) - */ -object CheckSupport {} diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/GroupLaws.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/GroupLaws.scala deleted file mode 100644 index d2775359be..0000000000 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/GroupLaws.scala +++ /dev/null @@ -1,100 +0,0 @@ -package cats.algebra.laws - -import cats.kernel._ -import cats.kernel.instances.option._ - -import org.typelevel.discipline.Laws - -import org.scalacheck.{Arbitrary, Prop} -import org.scalacheck.Prop._ - -object GroupLaws { - def apply[A: Eq: Arbitrary]: GroupLaws[A] = new GroupLaws[A] { - def Equ = Eq[A] - def Arb = implicitly[Arbitrary[A]] - } -} - -trait GroupLaws[A] extends Laws { - - implicit def Equ: Eq[A] - implicit def Arb: Arbitrary[A] - - // groups - - def semigroup(implicit A: Semigroup[A]): GroupProperties = new GroupProperties( - name = "semigroup", - parents = Nil, - Rules.serializable(A), - Rules.associativity(A.combine), - Rules.repeat1("combineN")(A.combineN), - Rules.repeat2("combineN", "|+|")(A.combineN)(A.combine), - "combineAllOption" -> forAll { (xs: Vector[A]) => - A.combineAllOption(xs) ?== xs.reduceOption(A.combine) - } - ) - - def band(implicit A: Band[A]): GroupProperties = new GroupProperties( - name = "band", - parents = List(semigroup), - Rules.idempotence(A.combine), - "isIdempotent" -> Semigroup.isIdempotent[A] - ) - - def commutativeSemigroup(implicit A: CommutativeSemigroup[A]): GroupProperties = new GroupProperties( - name = "commutative semigroup", - parents = List(semigroup), - Rules.commutative(A.combine) - ) - - def semilattice(implicit A: Semilattice[A]): GroupProperties = new GroupProperties( - name = "semilattice", - parents = List(band, commutativeSemigroup) - ) - - def monoid(implicit A: Monoid[A]): GroupProperties = new GroupProperties( - name = "monoid", - parents = List(semigroup), - Rules.leftIdentity(A.empty)(A.combine), - Rules.rightIdentity(A.empty)(A.combine), - Rules.repeat0("combineN", "id", A.empty)(A.combineN), - Rules.collect0("combineAll", "id", A.empty)(A.combineAll), - Rules.isId("isEmpty", A.empty)(A.isEmpty), - "combineAll" -> forAll { (xs: Vector[A]) => - A.combineAll(xs) ?== (A.empty +: xs).reduce(A.combine) - } - ) - - def commutativeMonoid(implicit A: CommutativeMonoid[A]): GroupProperties = new GroupProperties( - name = "commutative monoid", - parents = List(monoid, commutativeSemigroup) - ) - - def boundedSemilattice(implicit A: BoundedSemilattice[A]): GroupProperties = new GroupProperties( - name = "boundedSemilattice", - parents = List(commutativeMonoid, semilattice) - ) - - def group(implicit A: Group[A]): GroupProperties = new GroupProperties( - name = "group", - parents = List(monoid), - Rules.leftInverse(A.empty)(A.combine)(A.inverse), - Rules.rightInverse(A.empty)(A.combine)(A.inverse), - Rules.consistentInverse("remove")(A.remove)(A.combine)(A.inverse) - ) - - def commutativeGroup(implicit A: CommutativeGroup[A]): GroupProperties = new GroupProperties( - name = "commutative group", - parents = List(group, commutativeMonoid) - ) - - // property classes - - class GroupProperties( - val name: String, - val parents: Seq[GroupProperties], - val props: (String, Prop)* - ) extends RuleSet { - val bases = Nil - } -} diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticePartialOrderLaws.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticePartialOrderTests.scala similarity index 94% rename from algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticePartialOrderLaws.scala rename to algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticePartialOrderTests.scala index d7ac19f9f1..02d170ffe6 100644 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticePartialOrderLaws.scala +++ b/algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticePartialOrderTests.scala @@ -10,14 +10,14 @@ import org.scalacheck.Prop._ import cats.algebra.instances.boolean._ -object LatticePartialOrderLaws { - def apply[A: Eq: Arbitrary] = new LatticePartialOrderLaws[A] { +object LatticePartialOrderTests { + def apply[A: Eq: Arbitrary] = new LatticePartialOrderTests[A] { def Equ = Eq[A] def Arb = implicitly[Arbitrary[A]] } } -trait LatticePartialOrderLaws[A] extends Laws { +trait LatticePartialOrderTests[A] extends Laws { implicit def Equ: Eq[A] implicit def Arb: Arbitrary[A] diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticeLaws.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticeTests.scala similarity index 64% rename from algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticeLaws.scala rename to algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticeTests.scala index 26fc296d2b..e03fa58504 100644 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticeLaws.scala +++ b/algebra-laws/shared/src/main/scala/cats/algebra/laws/LatticeTests.scala @@ -2,18 +2,19 @@ package cats.algebra.laws import cats.algebra._ import cats.algebra.lattice._ - +import cats.kernel.laws.discipline.{BoundedSemilatticeTests, SemilatticeTests} import org.scalacheck.{Arbitrary, Prop} import org.scalacheck.Prop._ +import org.typelevel.discipline.Laws -object LatticeLaws { - def apply[A: Eq: Arbitrary] = new LatticeLaws[A] { +object LatticeTests { + def apply[A: Eq: Arbitrary] = new LatticeTests[A] { def Equ = Eq[A] def Arb = implicitly[Arbitrary[A]] } } -trait LatticeLaws[A] extends GroupLaws[A] { +trait LatticeTests[A] extends Laws { implicit def Equ: Eq[A] implicit def Arb: Arbitrary[A] @@ -21,7 +22,7 @@ trait LatticeLaws[A] extends GroupLaws[A] { def joinSemilattice(implicit A: JoinSemilattice[A]) = new LatticeProperties( name = "joinSemilattice", parents = Nil, - join = Some(semilattice(A.joinSemilattice)), + join = Some(SemilatticeTests[A](A.joinSemilattice).semilattice), meet = None, Rules.serializable(A) ) @@ -30,15 +31,15 @@ trait LatticeLaws[A] extends GroupLaws[A] { name = "meetSemilattice", parents = Nil, join = None, - meet = Some(semilattice(A.meetSemilattice)), + meet = Some(SemilatticeTests[A](A.meetSemilattice).semilattice), Rules.serializable(A) ) def lattice(implicit A: Lattice[A]) = new LatticeProperties( name = "lattice", parents = Seq(joinSemilattice, meetSemilattice), - join = Some(semilattice(A.joinSemilattice)), - meet = Some(semilattice(A.meetSemilattice)), + join = Some(SemilatticeTests[A](A.joinSemilattice).semilattice), + meet = Some(SemilatticeTests[A](A.meetSemilattice).semilattice), "absorption" -> forAll { (x: A, y: A) => (A.join(x, A.meet(x, y)) ?== x) && (A.meet(x, A.join(x, y)) ?== x) } @@ -47,8 +48,8 @@ trait LatticeLaws[A] extends GroupLaws[A] { def distributiveLattice(implicit A: DistributiveLattice[A]) = new LatticeProperties( name = "distributiveLattice", parents = Seq(lattice), - join = Some(semilattice(A.joinSemilattice)), - meet = Some(semilattice(A.meetSemilattice)), + join = Some(SemilatticeTests[A](A.joinSemilattice).semilattice), + meet = Some(SemilatticeTests[A](A.meetSemilattice).semilattice), "distributive" -> forAll { (x: A, y: A, z: A) => (A.join(x, A.meet(y, z)) ?== A.meet(A.join(x, y), A.join(x, z))) && (A.meet(x, A.join(y, z)) ?== A.join(A.meet(x, y), A.meet(x, z))) @@ -58,7 +59,7 @@ trait LatticeLaws[A] extends GroupLaws[A] { def boundedJoinSemilattice(implicit A: BoundedJoinSemilattice[A]) = new LatticeProperties( name = "boundedJoinSemilattice", parents = Seq(joinSemilattice), - join = Some(boundedSemilattice(A.joinSemilattice)), + join = Some(BoundedSemilatticeTests(A.joinSemilattice).boundedSemilattice), meet = None ) @@ -66,42 +67,42 @@ trait LatticeLaws[A] extends GroupLaws[A] { name = "boundedMeetSemilattice", parents = Seq(meetSemilattice), join = None, - meet = Some(boundedSemilattice(A.meetSemilattice)) + meet = Some(BoundedSemilatticeTests(A.meetSemilattice).boundedSemilattice) ) def boundedJoinLattice(implicit A: Lattice[A] with BoundedJoinSemilattice[A]) = new LatticeProperties( name = "boundedJoinLattice", parents = Seq(boundedJoinSemilattice, lattice), - join = Some(boundedSemilattice(A.joinSemilattice)), - meet = Some(semilattice(A.meetSemilattice)) + join = Some(BoundedSemilatticeTests(A.joinSemilattice).boundedSemilattice), + meet = Some(SemilatticeTests(A.meetSemilattice).semilattice) ) def boundedMeetLattice(implicit A: Lattice[A] with BoundedMeetSemilattice[A]) = new LatticeProperties( name = "boundedMeetLattice", parents = Seq(boundedMeetSemilattice, lattice), - join = Some(semilattice(A.joinSemilattice)), - meet = Some(boundedSemilattice(A.meetSemilattice)) + join = Some(SemilatticeTests(A.joinSemilattice).semilattice), + meet = Some(BoundedSemilatticeTests(A.meetSemilattice).boundedSemilattice) ) def boundedLattice(implicit A: BoundedLattice[A]) = new LatticeProperties( name = "boundedLattice", parents = Seq(boundedJoinSemilattice, boundedMeetSemilattice, lattice), - join = Some(boundedSemilattice(A.joinSemilattice)), - meet = Some(boundedSemilattice(A.meetSemilattice)) + join = Some(BoundedSemilatticeTests(A.joinSemilattice).boundedSemilattice), + meet = Some(BoundedSemilatticeTests(A.meetSemilattice).boundedSemilattice) ) def boundedDistributiveLattice(implicit A: BoundedDistributiveLattice[A]) = new LatticeProperties( name = "boundedLattice", parents = Seq(boundedLattice, distributiveLattice), - join = Some(boundedSemilattice(A.joinSemilattice)), - meet = Some(boundedSemilattice(A.meetSemilattice)) + join = Some(BoundedSemilatticeTests(A.joinSemilattice).boundedSemilattice), + meet = Some(BoundedSemilatticeTests(A.meetSemilattice).boundedSemilattice) ) class LatticeProperties( val name: String, val parents: Seq[LatticeProperties], - val join: Option[GroupProperties], - val meet: Option[GroupProperties], + val join: Option[Laws#RuleSet], + val meet: Option[Laws#RuleSet], val props: (String, Prop)* ) extends RuleSet { private val _m = meet.map { "meet" -> _ } diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/LogicLaws.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/LogicTests.scala similarity index 90% rename from algebra-laws/shared/src/main/scala/cats/algebra/laws/LogicLaws.scala rename to algebra-laws/shared/src/main/scala/cats/algebra/laws/LogicTests.scala index 5d050430cd..874439469b 100644 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/LogicLaws.scala +++ b/algebra-laws/shared/src/main/scala/cats/algebra/laws/LogicTests.scala @@ -2,17 +2,18 @@ package cats.algebra.laws import cats.algebra._ import cats.algebra.lattice.{Bool, DeMorgan, GenBool, Heyting, Logic} +import cats.kernel.laws.discipline.{BoundedSemilatticeTests, SemilatticeTests} import org.scalacheck.{Arbitrary, Prop} import org.scalacheck.Prop._ -object LogicLaws { - def apply[A: Eq: Arbitrary] = new LogicLaws[A] { +object LogicTests { + def apply[A: Eq: Arbitrary] = new LogicTests[A] { def Equ = Eq[A] def Arb = implicitly[Arbitrary[A]] } } -trait LogicLaws[A] extends LatticeLaws[A] { +trait LogicTests[A] extends LatticeTests[A] { def heyting(implicit A: Heyting[A]) = new LogicProperties( name = "heyting", @@ -49,8 +50,8 @@ trait LogicLaws[A] extends LatticeLaws[A] { ll = new LatticeProperties( name = "lowerBoundedDistributiveLattice", parents = Seq(boundedJoinSemilattice, distributiveLattice), - join = Some(boundedSemilattice(A.joinSemilattice)), - meet = Some(semilattice(A.meetSemilattice)) + join = Some(BoundedSemilatticeTests(A.joinSemilattice).boundedSemilattice), + meet = Some(SemilatticeTests(A.meetSemilattice).semilattice) ), """x\y ∧ y = 0""" -> forAll { (x: A, y: A) => A.and(A.without(x, y), y) ?== A.zero diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/RingLaws.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/RingTests.scala similarity index 86% rename from algebra-laws/shared/src/main/scala/cats/algebra/laws/RingLaws.scala rename to algebra-laws/shared/src/main/scala/cats/algebra/laws/RingTests.scala index 807c719c02..7486313601 100644 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/RingLaws.scala +++ b/algebra-laws/shared/src/main/scala/cats/algebra/laws/RingTests.scala @@ -3,56 +3,47 @@ package algebra package laws import cats.algebra.ring._ - +import cats.kernel.laws.discipline.{ + CommutativeGroupTests, + CommutativeMonoidTests, + CommutativeSemigroupTests, + GroupTests, + MonoidTests, + SemigroupTests +} import cats.platform.Platform - -import org.typelevel.discipline.Predicate - +import org.typelevel.discipline.{Laws, Predicate} import org.scalacheck.{Arbitrary, Prop} import org.scalacheck.Arbitrary._ import org.scalacheck.Prop._ -object RingLaws { - def apply[A: Eq: Arbitrary: AdditiveMonoid]: RingLaws[A] = +object RingTests { + def apply[A: Eq: Arbitrary: AdditiveMonoid]: RingTests[A] = withPred[A](new Predicate[A] { def apply(a: A): Boolean = Eq[A].neqv(a, AdditiveMonoid[A].zero) }) - def withPred[A](pred0: Predicate[A])(implicit eqv: Eq[A], arb: Arbitrary[A]): RingLaws[A] = new RingLaws[A] { + def withPred[A](pred0: Predicate[A])(implicit eqv: Eq[A], arb: Arbitrary[A]): RingTests[A] = new RingTests[A] { def Arb = arb + def Equ = eqv def pred = pred0 - val nonZeroLaws = new GroupLaws[A] { - def Arb = Arbitrary(arbitrary[A](arb).filter(pred)) - def Equ = eqv - } } } -trait RingLaws[A] extends GroupLaws[A] { self => +trait RingTests[A] extends Laws { self => - // must be a val (stable identifier) - val nonZeroLaws: GroupLaws[A] def pred: Predicate[A] - def withPred(pred0: Predicate[A], replace: Boolean = true): RingLaws[A] = - RingLaws.withPred(if (replace) pred0 else pred && pred0)(Equ, Arb) - - def setNonZeroParents(props: nonZeroLaws.GroupProperties, - parents: Seq[nonZeroLaws.GroupProperties] - ): nonZeroLaws.GroupProperties = - new nonZeroLaws.GroupProperties( - name = props.name, - parents = parents, - props = props.props: _* - ) + def withPred(pred0: Predicate[A], replace: Boolean = true): RingTests[A] = + RingTests.withPred(if (replace) pred0 else pred && pred0)(Equ, Arb) implicit def Arb: Arbitrary[A] - implicit def Equ: Eq[A] = nonZeroLaws.Equ + implicit def Equ: Eq[A] // additive groups def additiveSemigroup(implicit A: AdditiveSemigroup[A]) = new AdditiveProperties( - base = semigroup(A.additive), + base = SemigroupTests(A.additive).semigroup, parents = Nil, Rules.serializable(A), Rules.repeat1("sumN")(A.sumN), @@ -60,37 +51,37 @@ trait RingLaws[A] extends GroupLaws[A] { self => ) def additiveCommutativeSemigroup(implicit A: AdditiveCommutativeSemigroup[A]) = new AdditiveProperties( - base = commutativeSemigroup(A.additive), + base = CommutativeSemigroupTests(A.additive).commutativeSemigroup, parents = List(additiveSemigroup) ) def additiveMonoid(implicit A: AdditiveMonoid[A]) = new AdditiveProperties( - base = monoid(A.additive), + base = MonoidTests(A.additive).monoid, parents = List(additiveSemigroup), Rules.repeat0("sumN", "zero", A.zero)(A.sumN), Rules.collect0("sum", "zero", A.zero)(A.sum) ) def additiveCommutativeMonoid(implicit A: AdditiveCommutativeMonoid[A]) = new AdditiveProperties( - base = commutativeMonoid(A.additive), + base = CommutativeMonoidTests(A.additive).commutativeMonoid, parents = List(additiveMonoid) ) def additiveGroup(implicit A: AdditiveGroup[A]) = new AdditiveProperties( - base = group(A.additive), + base = GroupTests(A.additive).group, parents = List(additiveMonoid), Rules.consistentInverse("subtract")(A.minus)(A.plus)(A.negate) ) def additiveCommutativeGroup(implicit A: AdditiveCommutativeGroup[A]) = new AdditiveProperties( - base = commutativeGroup(A.additive), + base = CommutativeGroupTests(A.additive).commutativeGroup, parents = List(additiveGroup) ) // multiplicative groups def multiplicativeSemigroup(implicit A: MultiplicativeSemigroup[A]) = new MultiplicativeProperties( - base = semigroup(A.multiplicative), + base = SemigroupTests(A.multiplicative).semigroup, nonZeroBase = None, parent = None, Rules.serializable(A), @@ -100,13 +91,13 @@ trait RingLaws[A] extends GroupLaws[A] { self => def multiplicativeCommutativeSemigroup(implicit A: MultiplicativeCommutativeSemigroup[A]) = new MultiplicativeProperties( - base = semigroup(A.multiplicative), + base = CommutativeSemigroupTests(A.multiplicative).commutativeSemigroup, nonZeroBase = None, parent = Some(multiplicativeSemigroup) ) def multiplicativeMonoid(implicit A: MultiplicativeMonoid[A]) = new MultiplicativeProperties( - base = monoid(A.multiplicative), + base = MonoidTests(A.multiplicative).monoid, nonZeroBase = None, parent = Some(multiplicativeSemigroup), Rules.repeat0("pow", "one", A.one)(A.pow), @@ -114,14 +105,14 @@ trait RingLaws[A] extends GroupLaws[A] { self => ) def multiplicativeCommutativeMonoid(implicit A: MultiplicativeCommutativeMonoid[A]) = new MultiplicativeProperties( - base = commutativeMonoid(A.multiplicative), + base = CommutativeMonoidTests(A.multiplicative).commutativeMonoid, nonZeroBase = None, parent = Some(multiplicativeMonoid) ) def multiplicativeGroup(implicit A: MultiplicativeGroup[A]) = new MultiplicativeProperties( - base = monoid(A.multiplicative), - nonZeroBase = Some(setNonZeroParents(nonZeroLaws.group(A.multiplicative), Nil)), + base = MonoidTests(A.multiplicative).monoid, + nonZeroBase = Some(GroupTests(A.multiplicative).group), parent = Some(multiplicativeMonoid), // pred is used to ensure y is not zero. "consistent division" -> forAll { (x: A, y: A) => @@ -130,9 +121,11 @@ trait RingLaws[A] extends GroupLaws[A] { self => ) def multiplicativeCommutativeGroup(implicit A: MultiplicativeCommutativeGroup[A]) = new MultiplicativeProperties( - base = commutativeMonoid(A.multiplicative), - nonZeroBase = - Some(setNonZeroParents(nonZeroLaws.commutativeGroup(A.multiplicative), multiplicativeGroup.nonZeroBase.toSeq)), + base = CommutativeMonoidTests(A.multiplicative).commutativeMonoid, + nonZeroBase = Some { + val commutativeGroup = CommutativeGroupTests(A.multiplicative).commutativeGroup + new DefaultRuleSet(commutativeGroup.name, Some(multiplicativeGroup), commutativeGroup.props: _*) + }, parent = Some(multiplicativeGroup) ) @@ -340,7 +333,7 @@ trait RingLaws[A] extends GroupLaws[A] { self => // property classes class AdditiveProperties( - val base: GroupLaws[A]#GroupProperties, + val base: Laws#RuleSet, val parents: Seq[AdditiveProperties], val props: (String, Prop)* ) extends RuleSet { @@ -349,8 +342,8 @@ trait RingLaws[A] extends GroupLaws[A] { self => } class MultiplicativeProperties( - val base: GroupLaws[A]#GroupProperties, - val nonZeroBase: Option[nonZeroLaws.GroupProperties], + val base: Laws#RuleSet, + val nonZeroBase: Option[Laws#RuleSet], val parent: Option[MultiplicativeProperties], val props: (String, Prop)* ) extends RuleSet diff --git a/algebra-laws/shared/src/test/scala/cats/algebra/laws/LawTests.scala b/algebra-laws/shared/src/test/scala/cats/algebra/laws/LawTests.scala index c5bfb57b1b..346d9705e5 100644 --- a/algebra-laws/shared/src/test/scala/cats/algebra/laws/LawTests.scala +++ b/algebra-laws/shared/src/test/scala/cats/algebra/laws/LawTests.scala @@ -5,14 +5,12 @@ package laws import cats.algebra.lattice._ import cats.algebra.ring._ import cats.algebra.instances.all._ -import cats.algebra.instances.BigDecimalAlgebra import cats.platform.Platform import org.scalacheck.{Arbitrary, Cogen} import Arbitrary.arbitrary -import cats.kernel.laws.discipline.{EqTests, OrderTests, PartialOrderTests} +import cats.algebra.instances.BigDecimalAlgebra import scala.collection.immutable.BitSet -import scala.util.Random class LawTests extends munit.DisciplineSuite { @@ -21,14 +19,6 @@ class LawTests extends munit.DisciplineSuite { implicit val intLattice: BoundedDistributiveLattice[Int] = IntMinMaxLattice implicit val longLattice: BoundedDistributiveLattice[Long] = LongMinMaxLattice - implicit def groupLaws[A: Eq: Arbitrary]: GroupLaws[A] = GroupLaws[A] - implicit def logicLaws[A: Eq: Arbitrary]: LogicLaws[A] = LogicLaws[A] - - implicit def latticeLaws[A: Eq: Arbitrary]: LatticeLaws[A] = LatticeLaws[A] - implicit def ringLaws[A: Eq: Arbitrary: AdditiveMonoid]: RingLaws[A] = RingLaws[A] - implicit def baseLaws[A: Eq: Arbitrary]: BaseLaws[A] = BaseLaws[A] - implicit def latticePartialOrderLaws[A: Eq: Arbitrary]: LatticePartialOrderLaws[A] = LatticePartialOrderLaws[A] - case class HasEq[A](a: A) object HasEq { @@ -49,83 +39,50 @@ class LawTests extends munit.DisciplineSuite { Cogen[A].contramap[HasPartialOrder[A]](_.a) } - checkAll("Boolean", OrderTests[Boolean].order) //("Boolean").check(_.order) - checkAll("Boolean", LogicLaws[Boolean].bool) - checkAll("SimpleHeyting", LogicLaws[SimpleHeyting].logic(Logic.fromHeyting(Heyting[SimpleHeyting]))) - checkAll("SimpleHeyting", LogicLaws[SimpleHeyting].heyting) - checkAll("SimpleDeMorgan", LogicLaws[SimpleDeMorgan].deMorgan) - checkAll("Boolean", LogicLaws[Boolean].deMorgan(DeMorgan.fromBool(Bool[Boolean]))) - checkAll("Boolean", LatticePartialOrderLaws[Boolean].boundedLatticePartialOrder) - checkAll("Boolean", RingLaws[Boolean].boolRing(booleanRing)) + checkAll("Boolean", LogicTests[Boolean].bool) + checkAll("SimpleHeyting", LogicTests[SimpleHeyting].logic(Logic.fromHeyting(Heyting[SimpleHeyting]))) + checkAll("SimpleHeyting", LogicTests[SimpleHeyting].heyting) + checkAll("SimpleDeMorgan", LogicTests[SimpleDeMorgan].deMorgan) + checkAll("Boolean", LogicTests[Boolean].deMorgan(DeMorgan.fromBool(Bool[Boolean]))) + checkAll("Boolean", LatticePartialOrderTests[Boolean].boundedLatticePartialOrder) + checkAll("Boolean", RingTests[Boolean].boolRing(booleanRing)) // ensure that Bool[A].asBoolRing is a valid BoolRing - checkAll("Boolean-ring-from-bool", RingLaws[Boolean].boolRing(new BoolRingFromBool[Boolean](Bool[Boolean]))) + checkAll("Boolean-ring-from-bool", RingTests[Boolean].boolRing(new BoolRingFromBool[Boolean](Bool[Boolean]))) // ensure that BoolRing[A].asBool is a valid Bool - checkAll("Boolean- bool-from-ring", LogicLaws[Boolean].bool(new BoolFromBoolRing(booleanRing))) + checkAll("Boolean- bool-from-ring", LogicTests[Boolean].bool(new BoolFromBoolRing(booleanRing))) - checkAll("String", OrderTests[String].order) - checkAll("String", GroupLaws[String].monoid) + checkAll("Set[Byte]", LogicTests[Set[Byte]].generalizedBool) + checkAll("Set[Byte]", RingTests[Set[Byte]].boolRng(setBoolRng[Byte])) + checkAll("Set[Byte]-bool-from-rng", LogicTests[Set[Byte]].generalizedBool(new GenBoolFromBoolRng(setBoolRng))) + checkAll("Set[Byte]-rng-from-bool", RingTests[Set[Byte]].boolRng(new BoolRngFromGenBool(GenBool[Set[Byte]]))) + checkAll("Set[Int]", RingTests[Set[Int]].semiring) + checkAll("Set[String]", RingTests[Set[String]].semiring) - { - checkAll("Option[HasEq[Int]]", EqTests[Option[HasEq[Int]]].eqv) - checkAll("Option[HasPartialOrder[Int]]", PartialOrderTests[Option[HasPartialOrder[Int]]].partialOrder) - checkAll("Option[Int]", OrderTests[Option[Int]].order) - checkAll("Option[Int]", GroupLaws[Option[Int]].monoid) - checkAll("Option[HasEq[String]]", EqTests[Option[HasEq[String]]].eqv) - checkAll("Option[HasPartialOrder[String]]", PartialOrderTests[Option[HasPartialOrder[String]]].partialOrder) - checkAll("Option[String]", OrderTests[Option[String]].order) - checkAll("Option[String]", GroupLaws[Option[String]].monoid) - } + checkAll("Map[Char, Int]", RingTests[Map[Char, Int]].semiring) + checkAll("Map[Int, BigInt]", RingTests[Map[Int, BigInt]].semiring) - checkAll("List[HasEq[Int]]", EqTests[List[HasEq[Int]]].eqv) - checkAll("List[HasPartialOrder[Int]]", PartialOrderTests[List[HasPartialOrder[Int]]].partialOrder) - checkAll("List[Int]", OrderTests[List[Int]].order) - checkAll("List[Int]", GroupLaws[List[Int]].monoid) - checkAll("List[HasEq[String]]", EqTests[List[HasEq[String]]].eqv) - checkAll("List[HasPartialOrder[String]]", PartialOrderTests[List[HasPartialOrder[String]]].partialOrder) - checkAll("List[String]", OrderTests[List[String]].order) - checkAll("List[String]", GroupLaws[List[String]].monoid) - - checkAll("Set[Byte]", LogicLaws[Set[Byte]].generalizedBool) - checkAll("Set[Byte]", RingLaws[Set[Byte]].boolRng(setBoolRng[Byte])) - checkAll("Set[Byte]-bool-from-rng", LogicLaws[Set[Byte]].generalizedBool(new GenBoolFromBoolRng(setBoolRng))) - checkAll("Set[Byte]-rng-from-bool", RingLaws[Set[Byte]].boolRng(new BoolRngFromGenBool(GenBool[Set[Byte]]))) - checkAll("Set[Int]", PartialOrderTests[Set[Int]].partialOrder) - checkAll("Set[Int]", RingLaws[Set[Int]].semiring) - checkAll("Set[String]", RingLaws[Set[String]].semiring) - - checkAll("Map[Char, Int]", EqTests[Map[Char, Int]].eqv) - checkAll("Map[Char, Int]", RingLaws[Map[Char, Int]].semiring) - checkAll("Map[Int, BigInt]", EqTests[Map[Int, BigInt]].eqv) - checkAll("Map[Int, BigInt]", RingLaws[Map[Int, BigInt]].semiring) - - checkAll("Byte", OrderTests[Byte].order) - checkAll("Byte", RingLaws[Byte].commutativeRing) - checkAll("Byte", LatticeLaws[Byte].lattice) - - checkAll("Short", OrderTests[Short].order) - checkAll("Short", RingLaws[Short].commutativeRing) - checkAll("Short", LatticeLaws[Short].lattice) - - checkAll("Char", OrderTests[Char].order) - - checkAll("Int", OrderTests[Int].order) - checkAll("Int", RingLaws[Int].commutativeRing) - checkAll("Int", LatticeLaws[Int].boundedDistributiveLattice) + checkAll("Byte", RingTests[Byte].commutativeRing) + checkAll("Byte", LatticeTests[Byte].lattice) + + checkAll("Short", RingTests[Short].commutativeRing) + checkAll("Short", LatticeTests[Short].lattice) + + checkAll("Int", RingTests[Int].commutativeRing) + checkAll("Int", LatticeTests[Int].boundedDistributiveLattice) { - checkAll("Int", RingLaws[Int].commutativeRig) + checkAll("Int", RingTests[Int].commutativeRig) } - checkAll("Long", OrderTests[Long].order) - checkAll("Long", RingLaws[Long].commutativeRing) - checkAll("Long", LatticeLaws[Long].boundedDistributiveLattice) + checkAll("Long", RingTests[Long].commutativeRing) + checkAll("Long", LatticeTests[Long].boundedDistributiveLattice) - checkAll("BigInt", RingLaws[BigInt].euclideanRing) + checkAll("BigInt", RingTests[BigInt].euclideanRing) - checkAll("FPApprox[Float]", RingLaws[FPApprox[Float]].approxField) - checkAll("FPApprox[Double]", RingLaws[FPApprox[Double]].approxField) + checkAll("FPApprox[Float]", RingTests[FPApprox[Float]].approxField) + checkAll("FPApprox[Double]", RingTests[FPApprox[Double]].approxField) // let's limit our BigDecimal-related tests to the JVM for now. if (Platform.isJvm) { @@ -139,7 +96,7 @@ class LawTests extends munit.DisciplineSuite { // BigDecimal does have numerical errors, so we can't pass all of // the field laws. - checkAll("BigDecimal", RingLaws[BigDecimal].ring) + checkAll("BigDecimal", RingTests[BigDecimal].ring) } { @@ -150,83 +107,23 @@ class LawTests extends munit.DisciplineSuite { implicit val epsBigDecimal = FPApprox.Epsilon.bigDecimalEpsilon(mc) implicit val algebra: FPApproxAlgebra[BigDecimal] = FPApprox.fpApproxAlgebra(new BigDecimalAlgebra(mc), Order[BigDecimal], epsBigDecimal) - checkAll("FPApprox[BigDecimal]", RingLaws[FPApprox[BigDecimal]].field(algebra)) + checkAll("FPApprox[BigDecimal]", RingTests[FPApprox[BigDecimal]].field(algebra)) } } else () { implicit val arbBitSet: Arbitrary[BitSet] = Arbitrary(arbitrary[List[Byte]].map(s => BitSet(s.map(_ & 0xff): _*))) - checkAll("BitSet", LogicLaws[BitSet].generalizedBool) - } - - checkAll("(Int, Int)", RingLaws[(Int, Int)].ring) - - { - implicit val band = new Band[(Int, Int)] { - def combine(a: (Int, Int), b: (Int, Int)) = (a._1, b._2) - } - checkAll("(Int, Int) Band", GroupLaws[(Int, Int)].band) + checkAll("BitSet", LogicTests[BitSet].generalizedBool) } - checkAll("Unit", OrderTests[Unit].order) - checkAll("Unit", RingLaws[Unit].commutativeRing) - checkAll("Unit", RingLaws[Unit].multiplicativeMonoid) - checkAll("Unit", LatticeLaws[Unit].boundedSemilattice) - - { - // In order to check the monoid laws for `Order[N]`, we need - // `Arbitrary[Order[N]]` and `Eq[Order[N]]` instances. - // Here we have a bit of a hack to create these instances. - val nMax: Int = 13 - final case class N(n: Int) { require(n >= 0 && n < nMax) } - // The arbitrary `Order[N]` values are created by mapping N values to random - // integers. - implicit val arbNOrder: Arbitrary[Order[N]] = Arbitrary(arbitrary[Int].map { seed => - val order = new Random(seed).shuffle(Vector.range(0, nMax)) - Order.by { (n: N) => order(n.n) } - }) - // The arbitrary `Eq[N]` values are created by mapping N values to random - // integers. - implicit val arbNEq: Arbitrary[Eq[N]] = Arbitrary(arbitrary[Int].map { seed => - val mapping = new Random(seed).shuffle(Vector.range(0, nMax)) - Eq.by { (n: N) => mapping(n.n) } - }) - // needed because currently we don't have Vector instances - implicit val vectorNEq: Eq[Vector[N]] = Eq.fromUniversalEquals - // The `Eq[Order[N]]` instance enumerates all possible `N` values in a - // `Vector` and considers two `Order[N]` instances to be equal if they - // result in the same sorting of that vector. - implicit val NOrderEq: Eq[Order[N]] = Eq.by { (order: Order[N]) => - Vector.tabulate(nMax)(N).sorted(order.toOrdering) - } - implicit val NEqEq: Eq[Eq[N]] = new Eq[Eq[N]] { - def eqv(a: Eq[N], b: Eq[N]) = - Iterator - .tabulate(nMax)(N) - .flatMap { x => Iterator.tabulate(nMax)(N).map((x, _)) } - .forall { case (x, y) => a.eqv(x, y) == b.eqv(x, y) } - } - - implicit val monoidOrderN: Monoid[Order[N]] = Order.whenEqualMonoid[N] - checkAll("Order[N]", GroupLaws[Order[N]].monoid) - - { - implicit val bsEqN: BoundedSemilattice[Eq[N]] = Eq.allEqualBoundedSemilattice[N] - checkAll("Eq[N]", GroupLaws[Eq[N]].boundedSemilattice) - } - { - implicit val sEqN: Semilattice[Eq[N]] = Eq.anyEqualSemilattice[N] - checkAll("Eq[N]", GroupLaws[Eq[N]].semilattice) - } - } + checkAll("(Int, Int)", RingTests[(Int, Int)].ring) - // checkAll("Int", "fromOrdering", OrderLaws[Int].order(Order.fromOrdering[Int])) - checkAll("Array[Int]", OrderTests[Array[Int]].order) - checkAll("Array[Int]", PartialOrderTests[Array[Int]].partialOrder) + checkAll("Unit", RingTests[Unit].commutativeRing) + checkAll("Unit", RingTests[Unit].multiplicativeMonoid) // Rational tests do not return on Scala-js, so we make them JVM only. - if (Platform.isJvm) checkAll("Rat", RingLaws[Rat].field) + if (Platform.isJvm) checkAll("Rat", RingTests[Rat].field) else () test("Field.fromDouble with subnormal") {