From 513086720153726c3eedc8eba843040d3da07a70 Mon Sep 17 00:00:00 2001 From: Arman Bilge Date: Sat, 15 May 2021 03:14:16 -0700 Subject: [PATCH] Add kernel-laws dependency and refactor --- .../cats/algebra/laws/platform/Platform.scala | 10 -- .../cats/algebra/laws/platform/Platform.scala | 10 -- .../cats/algebra/laws/platform/Platform.scala | 10 -- .../cats/algebra/laws/IsSerializable.scala | 41 ------ .../scala/cats/algebra/laws/OrderLaws.scala | 121 ------------------ .../scala/cats/algebra/laws/RingLaws.scala | 2 +- .../main/scala/cats/algebra/laws/Rules.scala | 7 +- .../scala/cats/algebra/laws/FPApprox.scala | 2 +- .../scala/cats/algebra/laws/LawTests.scala | 57 ++++----- build.sbt | 2 +- 10 files changed, 33 insertions(+), 229 deletions(-) delete mode 100644 algebra-laws/js/src/main/scala/cats/algebra/laws/platform/Platform.scala delete mode 100644 algebra-laws/jvm/src/main/scala/cats/algebra/laws/platform/Platform.scala delete mode 100644 algebra-laws/native/src/main/scala/cats/algebra/laws/platform/Platform.scala delete mode 100644 algebra-laws/shared/src/main/scala/cats/algebra/laws/IsSerializable.scala delete mode 100644 algebra-laws/shared/src/main/scala/cats/algebra/laws/OrderLaws.scala diff --git a/algebra-laws/js/src/main/scala/cats/algebra/laws/platform/Platform.scala b/algebra-laws/js/src/main/scala/cats/algebra/laws/platform/Platform.scala deleted file mode 100644 index c22a3b2c6c..0000000000 --- a/algebra-laws/js/src/main/scala/cats/algebra/laws/platform/Platform.scala +++ /dev/null @@ -1,10 +0,0 @@ -package cats.algebra.laws.platform - -private[laws] object Platform { - // using `final val` makes compiler constant-fold any use of these values, dropping dead code automatically - // $COVERAGE-OFF$ - final val isJvm = false - final val isJs = true - final val isNative = false - // $COVERAGE-ON$ -} diff --git a/algebra-laws/jvm/src/main/scala/cats/algebra/laws/platform/Platform.scala b/algebra-laws/jvm/src/main/scala/cats/algebra/laws/platform/Platform.scala deleted file mode 100644 index 91ca1535b1..0000000000 --- a/algebra-laws/jvm/src/main/scala/cats/algebra/laws/platform/Platform.scala +++ /dev/null @@ -1,10 +0,0 @@ -package cats.algebra.laws.platform - -private[laws] object Platform { - // using `final val` makes compiler constant-fold any use of these values, dropping dead code automatically - // $COVERAGE-OFF$ - final val isJvm = true - final val isJs = false - final val isNative = false - // $COVERAGE-ON$ -} diff --git a/algebra-laws/native/src/main/scala/cats/algebra/laws/platform/Platform.scala b/algebra-laws/native/src/main/scala/cats/algebra/laws/platform/Platform.scala deleted file mode 100644 index 5abb255817..0000000000 --- a/algebra-laws/native/src/main/scala/cats/algebra/laws/platform/Platform.scala +++ /dev/null @@ -1,10 +0,0 @@ -package cats.algebra.laws.platform - -private[laws] object Platform { - // using `final val` makes compiler constant-fold any use of these values, dropping dead code automatically - // $COVERAGE-OFF$ - final val isJvm = false - final val isJs = false - final val isNative = true - // $COVERAGE-ON$ -} diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/IsSerializable.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/IsSerializable.scala deleted file mode 100644 index ee5839672e..0000000000 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/IsSerializable.scala +++ /dev/null @@ -1,41 +0,0 @@ -package cats.algebra.laws - -import cats.algebra.laws.platform.Platform -import org.scalacheck.Prop -import org.scalacheck.Prop._ -import scala.util.control.NonFatal -import scala.util.DynamicVariable - -/** - * Object with a dynamic variable that allows users to skip the - * serialization tests for certain instances. - */ -private[laws] object IsSerializable { - val runTests = new DynamicVariable[Boolean](true) - def apply(): Boolean = Platform.isJvm && runTests.value - - def testSerialization[M](m: M): Prop.Result = - if (Platform.isJvm) { - import java.io._ - val baos = new ByteArrayOutputStream() - val oos = new ObjectOutputStream(baos) - var ois: ObjectInputStream = null // scalastyle:ignore null - try { - oos.writeObject(m) - oos.close() - val bais = new ByteArrayInputStream(baos.toByteArray()) - ois = new ObjectInputStream(bais) - ois.readObject() // just ensure we can read it back - ois.close() - Result(status = Proof) - } catch { - case NonFatal(t) => - Result(status = Exception(t)) - } finally { - oos.close() - if (ois != null) ois.close() // scalastyle:ignore null - } - } else { - Result(status = Proof) - } -} diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/OrderLaws.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/OrderLaws.scala deleted file mode 100644 index 641bb53326..0000000000 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/OrderLaws.scala +++ /dev/null @@ -1,121 +0,0 @@ -package cats.algebra.laws - -import cats.kernel._ - -import org.typelevel.discipline.Laws - -import org.scalacheck.{Arbitrary, Cogen, Prop} -import org.scalacheck.Prop._ - -import cats.kernel.instances.all._ - -object OrderLaws { - def apply[A: Eq: Arbitrary: Cogen]: OrderLaws[A] = - new OrderLaws[A] { - def Equ = Eq[A] - def Arb = implicitly[Arbitrary[A]] - def Cog = implicitly[Cogen[A]] - } -} - -trait OrderLaws[A] extends Laws { - - implicit def Equ: Eq[A] - implicit def Arb: Arbitrary[A] - implicit def Cog: Cogen[A] - - def eqv: OrderProperties = new OrderProperties( - name = "eq", - parent = None, - Rules.serializable(Equ), - "reflexitivity-eq" -> forAll { (x: A) => - x ?== x - }, - "symmetry-eq" -> forAll { (x: A, y: A) => - Equ.eqv(x, y) ?== Equ.eqv(y, x) - }, - "antisymmetry-eq" -> forAll { (x: A, y: A, f: A => A) => - !Equ.eqv(x, y) ?|| Equ.eqv(f(x), f(y)) - }, - "transitivity-eq" -> forAll { (x: A, y: A, z: A) => - !(Equ.eqv(x, y) && Equ.eqv(y, z)) ?|| Equ.eqv(x, z) - } - ) - - def partialOrder(implicit A: PartialOrder[A]): OrderProperties = new OrderProperties( - name = "partialOrder", - parent = Some(eqv), - Rules.serializable(A), - "reflexitivity" -> forAll { (x: A) => - x ?<= x - }, - "antisymmetry" -> forAll { (x: A, y: A) => - !(A.lteqv(x, y) && A.lteqv(y, x)) ?|| A.eqv(x, y) - }, - "transitivity" -> forAll { (x: A, y: A, z: A) => - !(A.lteqv(x, y) && A.lteqv(y, z)) ?|| A.lteqv(x, z) - }, - "gteqv" -> forAll { (x: A, y: A) => - A.lteqv(x, y) ?== A.gteqv(y, x) - }, - "lt" -> forAll { (x: A, y: A) => - A.lt(x, y) ?== (A.lteqv(x, y) && A.neqv(x, y)) - }, - "gt" -> forAll { (x: A, y: A) => - A.lt(x, y) ?== A.gt(y, x) - }, - "partialCompare" -> forAll { (x: A, y: A) => - val c = A.partialCompare(x, y) - ((c < 0) ?== A.lt(x, y)) && ((c == 0) ?== A.eqv(x, y)) && ((c > 0) ?== A.gt(x, y)) - }, - "pmin" -> forAll { (x: A, y: A) => - val c = A.partialCompare(x, y) - val m = A.pmin(x, y) - if (c < 0) m ?== Some(x) - else if (c == 0) (m ?== Some(x)) && (m ?== Some(y)) - else if (c > 0) m ?== Some(y) - else m ?== None - }, - "pmax" -> forAll { (x: A, y: A) => - val c = A.partialCompare(x, y) - val m = A.pmax(x, y) - if (c < 0) m ?== Some(y) - else if (c == 0) (m ?== Some(x)) && (m ?== Some(y)) - else if (c > 0) m ?== Some(x) - else m ?== None - } - ) - - def order(implicit A: Order[A]): OrderProperties = new OrderProperties( - name = "order", - parent = Some(partialOrder), - "totality" -> forAll { (x: A, y: A) => - A.lteqv(x, y) ?|| A.lteqv(y, x) - }, - "compare" -> forAll { (x: A, y: A) => - val c = A.compare(x, y) - ((c < 0) ?== A.lt(x, y)) && ((c == 0) ?== A.eqv(x, y)) && ((c > 0) ?== A.gt(x, y)) - }, - "min" -> forAll { (x: A, y: A) => - val c = A.compare(x, y) - val m = A.min(x, y) - if (c < 0) m ?== x - else if (c == 0) (m ?== x) && (m ?== y) - else m ?== y - }, - "max" -> forAll { (x: A, y: A) => - val c = A.compare(x, y) - val m = A.max(x, y) - if (c < 0) m ?== y - else if (c == 0) (m ?== x) && (m ?== y) - else m ?== x - } - ) - - class OrderProperties( - name: String, - parent: Option[RuleSet], - props: (String, Prop)* - ) extends DefaultRuleSet(name, parent, props: _*) - -} diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/RingLaws.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/RingLaws.scala index 308e9fb4bc..6c45641c36 100644 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/RingLaws.scala +++ b/algebra-laws/shared/src/main/scala/cats/algebra/laws/RingLaws.scala @@ -4,7 +4,7 @@ package laws import cats.algebra.ring._ -import cats.algebra.laws.platform.Platform +import cats.platform.Platform import org.typelevel.discipline.Predicate diff --git a/algebra-laws/shared/src/main/scala/cats/algebra/laws/Rules.scala b/algebra-laws/shared/src/main/scala/cats/algebra/laws/Rules.scala index 0130308dd8..5dffeb98eb 100644 --- a/algebra-laws/shared/src/main/scala/cats/algebra/laws/Rules.scala +++ b/algebra-laws/shared/src/main/scala/cats/algebra/laws/Rules.scala @@ -4,6 +4,7 @@ import cats.kernel._ import org.scalacheck.Prop._ import org.scalacheck.{Arbitrary, Prop} import cats.kernel.instances.boolean._ +import cats.kernel.laws.discipline.SerializableTests object Rules { @@ -95,9 +96,5 @@ object Rules { // ugly platform-specific code follows def serializable[M](m: M): (String, Prop) = - "serializable" -> (if (IsSerializable()) { - Prop(_ => Result(status = Proof)) - } else { - Prop(_ => IsSerializable.testSerialization(m)) - }) + SerializableTests.serializable(m).props.head } diff --git a/algebra-laws/shared/src/test/scala/cats/algebra/laws/FPApprox.scala b/algebra-laws/shared/src/test/scala/cats/algebra/laws/FPApprox.scala index 8b78672631..67d6bc2cef 100644 --- a/algebra-laws/shared/src/test/scala/cats/algebra/laws/FPApprox.scala +++ b/algebra-laws/shared/src/test/scala/cats/algebra/laws/FPApprox.scala @@ -66,7 +66,7 @@ object FPApprox { def exact[A: Rng: Order](a: A): FPApprox[A] = FPApprox(a, abs(a), 0) def approx[A: Rng: Order](a: A): FPApprox[A] = FPApprox(a, abs(a), 1) - trait Epsilon[A] { + trait Epsilon[A] extends Serializable { def minValue: A def epsilon: A def isFinite(a: A): Boolean 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 9305b8d4a4..815b880e13 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 @@ -6,11 +6,11 @@ import cats.algebra.lattice._ import cats.algebra.ring._ import cats.algebra.instances.all._ import cats.algebra.instances.BigDecimalAlgebra - -import cats.algebra.laws.platform.Platform - +import cats.platform.Platform import org.scalacheck.{Arbitrary, Cogen} import Arbitrary.arbitrary +import cats.kernel.laws.discipline.{EqTests, OrderTests, PartialOrderTests} + import scala.collection.immutable.BitSet import scala.util.Random @@ -21,7 +21,6 @@ class LawTests extends munit.DisciplineSuite { implicit val intLattice: BoundedDistributiveLattice[Int] = IntMinMaxLattice implicit val longLattice: BoundedDistributiveLattice[Long] = LongMinMaxLattice - implicit def orderLaws[A: Cogen: Eq: Arbitrary]: OrderLaws[A] = OrderLaws[A] implicit def groupLaws[A: Eq: Arbitrary]: GroupLaws[A] = GroupLaws[A] implicit def logicLaws[A: Eq: Arbitrary]: LogicLaws[A] = LogicLaws[A] @@ -50,7 +49,7 @@ class LawTests extends munit.DisciplineSuite { Cogen[A].contramap[HasPartialOrder[A]](_.a) } - checkAll("Boolean", OrderLaws[Boolean].order) //("Boolean").check(_.order) + 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) @@ -65,53 +64,53 @@ class LawTests extends munit.DisciplineSuite { // ensure that BoolRing[A].asBool is a valid Bool checkAll("Boolean- bool-from-ring", LogicLaws[Boolean].bool(new BoolFromBoolRing(booleanRing))) - checkAll("String", OrderLaws[String].order) + checkAll("String", OrderTests[String].order) checkAll("String", GroupLaws[String].monoid) { - checkAll("Option[HasEq[Int]]", OrderLaws[Option[HasEq[Int]]].eqv) - checkAll("Option[HasPartialOrder[Int]]", OrderLaws[Option[HasPartialOrder[Int]]].partialOrder) - checkAll("Option[Int]", OrderLaws[Option[Int]].order) + 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]]", OrderLaws[Option[HasEq[String]]].eqv) - checkAll("Option[HasPartialOrder[String]]", OrderLaws[Option[HasPartialOrder[String]]].partialOrder) - checkAll("Option[String]", OrderLaws[Option[String]].order) + 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("List[HasEq[Int]]", OrderLaws[List[HasEq[Int]]].eqv) - checkAll("List[HasPartialOrder[Int]]", OrderLaws[List[HasPartialOrder[Int]]].partialOrder) - checkAll("List[Int]", OrderLaws[List[Int]].order) + 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]]", OrderLaws[List[HasEq[String]]].eqv) - checkAll("List[HasPartialOrder[String]]", OrderLaws[List[HasPartialOrder[String]]].partialOrder) - checkAll("List[String]", OrderLaws[List[String]].order) + 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(GenBool[Set[Byte]].asBoolRing)) - checkAll("Set[Int]", OrderLaws[Set[Int]].partialOrder) + 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]", OrderLaws[Map[Char, Int]].eqv) + checkAll("Map[Char, Int]", EqTests[Map[Char, Int]].eqv) checkAll("Map[Char, Int]", RingLaws[Map[Char, Int]].semiring) - checkAll("Map[Int, BigInt]", OrderLaws[Map[Int, BigInt]].eqv) + checkAll("Map[Int, BigInt]", EqTests[Map[Int, BigInt]].eqv) checkAll("Map[Int, BigInt]", RingLaws[Map[Int, BigInt]].semiring) - checkAll("Byte", OrderLaws[Byte].order) + checkAll("Byte", OrderTests[Byte].order) checkAll("Byte", RingLaws[Byte].commutativeRing) checkAll("Byte", LatticeLaws[Byte].lattice) - checkAll("Short", OrderLaws[Short].order) + checkAll("Short", OrderTests[Short].order) checkAll("Short", RingLaws[Short].commutativeRing) checkAll("Short", LatticeLaws[Short].lattice) - checkAll("Char", OrderLaws[Char].order) + checkAll("Char", OrderTests[Char].order) - checkAll("Int", OrderLaws[Int].order) + checkAll("Int", OrderTests[Int].order) checkAll("Int", RingLaws[Int].commutativeRing) checkAll("Int", LatticeLaws[Int].boundedDistributiveLattice) @@ -119,7 +118,7 @@ class LawTests extends munit.DisciplineSuite { checkAll("Int", RingLaws[Int].commutativeRig) } - checkAll("Long", OrderLaws[Long].order) + checkAll("Long", OrderTests[Long].order) checkAll("Long", RingLaws[Long].commutativeRing) checkAll("Long", LatticeLaws[Long].boundedDistributiveLattice) @@ -170,7 +169,7 @@ class LawTests extends munit.DisciplineSuite { checkAll("(Int, Int) Band", GroupLaws[(Int, Int)].band) } - checkAll("Unit", OrderLaws[Unit].order) + checkAll("Unit", OrderTests[Unit].order) checkAll("Unit", RingLaws[Unit].commutativeRing) checkAll("Unit", RingLaws[Unit].multiplicativeMonoid) checkAll("Unit", LatticeLaws[Unit].boundedSemilattice) @@ -223,8 +222,8 @@ class LawTests extends munit.DisciplineSuite { } // checkAll("Int", "fromOrdering", OrderLaws[Int].order(Order.fromOrdering[Int])) - checkAll("Array[Int]", OrderLaws[Array[Int]].order) - checkAll("Array[Int]", OrderLaws[Array[Int]].partialOrder) + checkAll("Array[Int]", OrderTests[Array[Int]].order) + checkAll("Array[Int]", PartialOrderTests[Array[Int]].partialOrder) // Rational tests do not return on Scala-js, so we make them JVM only. if (Platform.isJvm) checkAll("Rat", RingLaws[Rat].field) diff --git a/build.sbt b/build.sbt index 4a8bfc11c3..32e726815e 100644 --- a/build.sbt +++ b/build.sbt @@ -709,7 +709,7 @@ lazy val algebraLaws = crossProject(JSPlatform, JVMPlatform, NativePlatform) .settings(Test / scalacOptions := (Test / scalacOptions).value.filter(_ != "-Xfatal-warnings")) .jsSettings(commonJsSettings) .jvmSettings(commonJvmSettings) - .dependsOn(kernel, algebra) + .dependsOn(kernelLaws, algebra) .nativeSettings(commonNativeSettings) lazy val core = crossProject(JSPlatform, JVMPlatform, NativePlatform)