diff --git a/build.sbt b/build.sbt index 7442f366..a4346598 100644 --- a/build.sbt +++ b/build.sbt @@ -7,13 +7,13 @@ import com.typesafe.tools.mima.plugin.MimaPlugin.mimaDefaultSettings lazy val scalaCheckVersion = "1.13.4" lazy val scalaTestVersion = "3.0.1" lazy val disciplineVersion = "0.7.2" -lazy val catsVersion = "1.0.0-MF" +lazy val catsVersion = "1.0.0-RC1" lazy val catalystsVersion = "0.0.5" lazy val buildSettings = Seq( organization := "org.typelevel", - scalaVersion := "2.12.3", - crossScalaVersions := Seq("2.10.6", "2.11.11", "2.12.3") + scalaVersion := "2.12.4", + crossScalaVersions := Seq("2.10.6", "2.11.11", "2.12.4") ) lazy val commonSettings = Seq( diff --git a/laws/src/main/scala/algebra/laws/AdditiveCommutativeGroupLaws.scala b/laws/src/main/scala/algebra/laws/AdditiveCommutativeGroupLaws.scala new file mode 100644 index 00000000..33c0aaee --- /dev/null +++ b/laws/src/main/scala/algebra/laws/AdditiveCommutativeGroupLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait AdditiveCommutativeGroupLaws[A] extends AdditiveGroupLaws[A] with AdditiveCommutativeMonoidLaws[A] { + override implicit def S: AdditiveCommutativeGroup[A] +} + +object AdditiveCommutativeGroupLaws { + def apply[A](implicit ev: AdditiveCommutativeGroup[A]): AdditiveCommutativeGroupLaws[A] = + new AdditiveCommutativeGroupLaws[A] { def S: AdditiveCommutativeGroup[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/AdditiveCommutativeMonoidLaws.scala b/laws/src/main/scala/algebra/laws/AdditiveCommutativeMonoidLaws.scala new file mode 100644 index 00000000..2832b653 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/AdditiveCommutativeMonoidLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait AdditiveCommutativeMonoidLaws[A] extends AdditiveMonoidLaws[A] with AdditiveCommutativeSemigroupLaws[A] { + override implicit def S: AdditiveCommutativeMonoid[A] +} + +object AdditiveCommutativeMonoidLaws { + def apply[A](implicit ev: AdditiveCommutativeMonoid[A]): AdditiveCommutativeMonoidLaws[A] = + new AdditiveCommutativeMonoidLaws[A] { def S: AdditiveCommutativeMonoid[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/AdditiveCommutativeSemigroupLaws.scala b/laws/src/main/scala/algebra/laws/AdditiveCommutativeSemigroupLaws.scala new file mode 100644 index 00000000..23250fb4 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/AdditiveCommutativeSemigroupLaws.scala @@ -0,0 +1,19 @@ +package algebra +package laws + +import algebra.ring._ +import cats.kernel.laws._ + + +trait AdditiveCommutativeSemigroupLaws[A] extends AdditiveSemigroupLaws[A] { + override implicit def S: AdditiveCommutativeSemigroup[A] + + def plusCommutative(x: A, y: A): IsEq[A] = + S.plus(x, y) <-> S.plus(y, x) + +} + +object AdditiveCommutativeSemigroupLaws { + def apply[A](implicit ev: AdditiveCommutativeSemigroup[A]): AdditiveCommutativeSemigroupLaws[A] = + new AdditiveCommutativeSemigroupLaws[A] { def S: AdditiveCommutativeSemigroup[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/AdditiveGroupLaws.scala b/laws/src/main/scala/algebra/laws/AdditiveGroupLaws.scala new file mode 100755 index 00000000..cf5c6c84 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/AdditiveGroupLaws.scala @@ -0,0 +1,25 @@ +package algebra +package laws + +import algebra.ring._ +import cats.kernel.laws._ + + +trait AdditiveGroupLaws[A] extends AdditiveMonoidLaws[A] { + override implicit def S: AdditiveGroup[A] + + def leftNegate(x: A): IsEq[A] = + S.plus(S.negate(x), x) <-> S.zero + + def rightNegate(x: A): IsEq[A] = + S.plus(x, S.negate(x)) <-> S.zero + + def consistentMinus(x: A, y: A): IsEq[A] = + S.minus(x, y) <-> S.plus(x, S.negate(y)) + +} + +object AdditiveGroupLaws { + def apply[A](implicit ev: AdditiveGroup[A]): AdditiveGroupLaws[A] = + new AdditiveGroupLaws[A] { def S: AdditiveGroup[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/AdditiveMonoidLaws.scala b/laws/src/main/scala/algebra/laws/AdditiveMonoidLaws.scala new file mode 100755 index 00000000..19aa5c65 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/AdditiveMonoidLaws.scala @@ -0,0 +1,29 @@ +package algebra.laws + +import algebra.ring._ +import cats.kernel.Eq +import cats.kernel.laws._ + +trait AdditiveMonoidLaws[A] extends AdditiveSemigroupLaws[A] { + override implicit def S: AdditiveMonoid[A] + + def leftZero(a: A): IsEq[A] = + S.plus(S.zero, a) <-> a + + def rightZero(a: A): IsEq[A] = + S.plus(a, S.zero) <-> a + + def sumN0(a: A): IsEq[A] = + S.sumN(a, 0) <-> S.zero + + def sumAll: IsEq[A] = + S.sum(Nil) <-> S.zero + + def isZero(a: A, eqv: Eq[A]): IsEq[Boolean] = + eqv.eqv(a, S.zero) <-> S.isZero(a)(eqv) +} + +object AdditiveMonoidLaws { + def apply[A](implicit ev: AdditiveMonoid[A]): AdditiveMonoidLaws[A] = + new AdditiveMonoidLaws[A] { def S: AdditiveMonoid[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/AdditiveSemigroupLaws.scala b/laws/src/main/scala/algebra/laws/AdditiveSemigroupLaws.scala new file mode 100755 index 00000000..b1249c13 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/AdditiveSemigroupLaws.scala @@ -0,0 +1,29 @@ +package algebra +package laws + +import algebra.ring._ +import cats.kernel.laws._ + +trait AdditiveSemigroupLaws[A] { + implicit def S: AdditiveSemigroup[A] + + def plusAssociative(x: A, y: A, z: A): IsEq[A] = + S.plus(S.plus(x, y), z) <-> S.plus(x, S.plus(y, z)) + + def sumN1(a: A): IsEq[A] = + S.sumN(a, 1) <-> a + + def sumN2(a: A): IsEq[A] = + S.sumN(a, 2) <-> S.plus(a, a) + + def sumN3(a: A): IsEq[A] = + S.sumN(a, 3) <-> S.plus(S.plus(a, a), a) + + def trySum(xs: Vector[A]): IsEq[Option[A]] = + S.trySum(xs) <-> xs.reduceOption(S.plus) +} + +object AdditiveSemigroupLaws { + def apply[A](implicit ev: AdditiveSemigroup[A]): AdditiveSemigroupLaws[A] = + new AdditiveSemigroupLaws[A] { def S: AdditiveSemigroup[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/BoundedDistributiveLatticeLaws.scala b/laws/src/main/scala/algebra/laws/BoundedDistributiveLatticeLaws.scala new file mode 100644 index 00000000..fcdd3e3b --- /dev/null +++ b/laws/src/main/scala/algebra/laws/BoundedDistributiveLatticeLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.lattice._ + +trait BoundedDistributiveLatticeLaws[A] extends BoundedLatticeLaws[A] with DistributiveLatticeLaws[A] { + override implicit def S: BoundedDistributiveLattice[A] +} + +object BoundedDistributiveLatticeLaws { + def apply[A](implicit ev: BoundedDistributiveLattice[A]): BoundedDistributiveLatticeLaws[A] = + new BoundedDistributiveLatticeLaws[A] { def S: BoundedDistributiveLattice[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/BoundedJoinLatticeLaws.scala b/laws/src/main/scala/algebra/laws/BoundedJoinLatticeLaws.scala new file mode 100644 index 00000000..591710b7 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/BoundedJoinLatticeLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.lattice._ + +trait BoundedJoinLatticeLaws[A] extends LatticeLaws[A] with BoundedJoinSemilatticeLaws[A] { + override implicit def S: Lattice[A] with BoundedJoinSemilattice[A] +} + +object BoundedJoinLatticeLaws { + def apply[A](implicit ev: Lattice[A] with BoundedJoinSemilattice[A]): BoundedJoinLatticeLaws[A] = + new BoundedJoinLatticeLaws[A] { def S: Lattice[A] with BoundedJoinSemilattice[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/BoundedJoinSemilatticeLaws.scala b/laws/src/main/scala/algebra/laws/BoundedJoinSemilatticeLaws.scala new file mode 100644 index 00000000..5d8c15ea --- /dev/null +++ b/laws/src/main/scala/algebra/laws/BoundedJoinSemilatticeLaws.scala @@ -0,0 +1,13 @@ +package algebra.laws + +import algebra.lattice._ +import cats.kernel.laws.BoundedSemilatticeLaws + +trait BoundedJoinSemilatticeLaws[A] extends JoinSemilatticeLaws[A] with BoundedSemilatticeLaws[A] { + override implicit def S: BoundedJoinSemilattice[A] +} + +object BoundedJoinSemilatticeLaws { + def apply[A](implicit ev: BoundedJoinSemilattice[A]): BoundedJoinSemilatticeLaws[A] = + new BoundedJoinSemilatticeLaws[A] { def S: BoundedJoinSemilattice[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/BoundedLatticeLaws.scala b/laws/src/main/scala/algebra/laws/BoundedLatticeLaws.scala new file mode 100644 index 00000000..e859aeb1 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/BoundedLatticeLaws.scala @@ -0,0 +1,14 @@ +package algebra +package laws + +import algebra.lattice._ + +trait BoundedLatticeLaws[A] extends LatticeLaws[A] with BoundedMeetLatticeLaws[A] with BoundedJoinLatticeLaws[A] { + override implicit def S: BoundedLattice[A] +} + +object BoundedLatticeLaws { + def apply[A](implicit ev: BoundedLattice[A]): BoundedLatticeLaws[A] = + new BoundedLatticeLaws[A] { def S: BoundedLattice[A] = ev } +} + diff --git a/laws/src/main/scala/algebra/laws/BoundedMeetLatticeLaws.scala b/laws/src/main/scala/algebra/laws/BoundedMeetLatticeLaws.scala new file mode 100644 index 00000000..d1e5de86 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/BoundedMeetLatticeLaws.scala @@ -0,0 +1,13 @@ +package algebra.laws + +import algebra.lattice._ + +trait BoundedMeetLatticeLaws[A] extends LatticeLaws[A] with BoundedMeetSemilatticeLaws[A] { + override implicit def S: Lattice[A] with BoundedMeetSemilattice[A] +} + +object BoundedMeetLatticeLaws { + def apply[A](implicit ev: Lattice[A] with BoundedMeetSemilattice[A]): BoundedMeetLatticeLaws[A] = + new BoundedMeetLatticeLaws[A] { def S: Lattice[A] with BoundedMeetSemilattice[A] = ev } +} + diff --git a/laws/src/main/scala/algebra/laws/BoundedMeetSemilatticeLaws.scala b/laws/src/main/scala/algebra/laws/BoundedMeetSemilatticeLaws.scala new file mode 100644 index 00000000..6a9decbb --- /dev/null +++ b/laws/src/main/scala/algebra/laws/BoundedMeetSemilatticeLaws.scala @@ -0,0 +1,13 @@ +package algebra.laws + +import cats.kernel.laws.BoundedSemilatticeLaws +import algebra.lattice._ + +trait BoundedMeetSemilatticeLaws[A] extends MeetSemilatticeLaws[A] with BoundedSemilatticeLaws[A] { + override implicit def S: BoundedMeetSemilattice[A] +} + +object BoundedMeetSemilatticeLaws { + def apply[A](implicit ev: BoundedMeetSemilattice[A]): BoundedMeetSemilatticeLaws[A] = + new BoundedMeetSemilatticeLaws[A] { def S: BoundedMeetSemilattice[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/CheckSupport.scala b/laws/src/main/scala/algebra/laws/CheckSupport.scala deleted file mode 100644 index 64b0ccd1..00000000 --- a/laws/src/main/scala/algebra/laws/CheckSupport.scala +++ /dev/null @@ -1,12 +0,0 @@ -package 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/laws/src/main/scala/algebra/laws/CommutativeRigLaws.scala b/laws/src/main/scala/algebra/laws/CommutativeRigLaws.scala new file mode 100755 index 00000000..2385e189 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/CommutativeRigLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait CommutativeRigLaws[A] extends RigLaws[A] with CommutativeSemiringLaws[A] with MultiplicativeCommutativeMonoidLaws[A] { + override implicit def S: CommutativeRig[A] +} + +object CommutativeRigLaws { + def apply[A](implicit ev: CommutativeRig[A]): CommutativeRigLaws[A] = + new CommutativeRigLaws[A] { def S: CommutativeRig[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/CommutativeRingLaws.scala b/laws/src/main/scala/algebra/laws/CommutativeRingLaws.scala new file mode 100755 index 00000000..bb711887 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/CommutativeRingLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait CommutativeRingLaws[A] extends RingLaws[A] with CommutativeRigLaws[A] with CommutativeRngLaws[A] { + override implicit def S: CommutativeRing[A] +} + +object CommutativeRingLaws { + def apply[A](implicit ev: CommutativeRing[A]): CommutativeRingLaws[A] = + new CommutativeRingLaws[A] { def S: CommutativeRing[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/CommutativeRngLaws.scala b/laws/src/main/scala/algebra/laws/CommutativeRngLaws.scala new file mode 100755 index 00000000..aa91f4a0 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/CommutativeRngLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait CommutativeRngLaws[A] extends CommutativeSemiringLaws[A] with RngLaws[A] { + override implicit def S: CommutativeRng[A] +} + +object CommutativeRngLaws { + def apply[A](implicit ev: CommutativeRng[A]): CommutativeRngLaws[A] = + new CommutativeRngLaws[A] { def S: CommutativeRng[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/CommutativeSemiringLaws.scala b/laws/src/main/scala/algebra/laws/CommutativeSemiringLaws.scala new file mode 100755 index 00000000..9415eea0 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/CommutativeSemiringLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait CommutativeSemiringLaws[A] extends SemiringLaws[A] with MultiplicativeCommutativeSemigroupLaws[A] { + override implicit def S: CommutativeSemiring[A] +} + +object CommutativeSemiringLaws { + def apply[A](implicit ev: CommutativeSemiring[A]): CommutativeSemiringLaws[A] = + new CommutativeSemiringLaws[A] { def S: CommutativeSemiring[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/DistributiveLatticeLaws.scala b/laws/src/main/scala/algebra/laws/DistributiveLatticeLaws.scala new file mode 100644 index 00000000..4c312d46 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/DistributiveLatticeLaws.scala @@ -0,0 +1,20 @@ +package algebra +package laws + +import algebra.lattice._ +import cats.kernel.laws._ + + +trait DistributiveLatticeLaws[A] extends LatticeLaws[A] { + override implicit def S: DistributiveLattice[A] + + def distributive(x: A, y: A, z: A)(implicit E: Eq[A]): IsEq[Boolean] = + (E.eqv(S.join(x, S.meet(y, z)), S.meet(S.join(x, y), S.join(x, z))) && + E.eqv(S.meet(x, S.join(y, z)), S.join(S.meet(x, y), S.meet(x, z)))) <-> true + +} + +object DistributiveLatticeLaws { + def apply[A](implicit ev: DistributiveLattice[A]): DistributiveLatticeLaws[A] = + new DistributiveLatticeLaws[A] { def S: DistributiveLattice[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/FieldLaws.scala b/laws/src/main/scala/algebra/laws/FieldLaws.scala new file mode 100755 index 00000000..9c0757ca --- /dev/null +++ b/laws/src/main/scala/algebra/laws/FieldLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait FieldLaws[A] extends CommutativeRingLaws[A] with MultiplicativeCommutativeGroupLaws[A] { + override implicit def S: Field[A] +} + +object FieldLaws { + def apply[A: Field]: FieldLaws[A] = + new FieldLaws[A] { def S: Field[A] = implicitly } +} diff --git a/laws/src/main/scala/algebra/laws/HeytingLaws.scala b/laws/src/main/scala/algebra/laws/HeytingLaws.scala new file mode 100644 index 00000000..4da36142 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/HeytingLaws.scala @@ -0,0 +1,19 @@ +package algebra.laws + +import algebra._ +import algebra.lattice._ + +import cats.kernel.laws._ + + +trait HeytingLaws[A] extends BoundedDistributiveLatticeLaws[A] { + override implicit def S: Heyting[A] + + def absorption(x: A, y: A)(implicit E: Eq[A]): IsEq[Boolean] = + (E.eqv(S.join(x, S.meet(x, y)), x) && E.eqv(S.meet(x, S.join(x, y)), x)) <-> true +} + +object HeytingLaws { + def apply[A](implicit ev: Heyting[A]): HeytingLaws[A] = + new HeytingLaws[A] { def S: Heyting[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/JoinSemilatticeLaws.scala b/laws/src/main/scala/algebra/laws/JoinSemilatticeLaws.scala new file mode 100644 index 00000000..de08b8b8 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/JoinSemilatticeLaws.scala @@ -0,0 +1,13 @@ +package algebra.laws + +import algebra.lattice.JoinSemilattice +import cats.kernel.laws.SemilatticeLaws + +trait JoinSemilatticeLaws[A] extends SemilatticeLaws[A] { + override implicit def S: JoinSemilattice[A] +} + +object JoinSemilatticeLaws { + def apply[A](implicit ev: JoinSemilattice[A]): JoinSemilatticeLaws[A] = + new JoinSemilatticeLaws[A] { def S: JoinSemilattice[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/LatticeLaws.scala b/laws/src/main/scala/algebra/laws/LatticeLaws.scala index 17d2e97e..22c330ba 100644 --- a/laws/src/main/scala/algebra/laws/LatticeLaws.scala +++ b/laws/src/main/scala/algebra/laws/LatticeLaws.scala @@ -5,111 +5,15 @@ import algebra.lattice._ import cats.kernel.laws._ -import org.scalacheck.{Arbitrary, Prop} -import org.scalacheck.Prop._ -object LatticeLaws { - def apply[A: Eq: Arbitrary] = new LatticeLaws[A] { - def Equ = Eq[A] - def Arb = implicitly[Arbitrary[A]] - } -} - -trait LatticeLaws[A] extends GroupLaws[A] { - - implicit def Equ: Eq[A] - implicit def Arb: Arbitrary[A] - - def joinSemilattice(implicit A: JoinSemilattice[A]) = new LatticeProperties( - name = "joinSemilattice", - parents = Nil, - join = Some(semilattice(A.joinSemilattice)), - meet = None, - Rules.serializable(A) - ) - - def meetSemilattice(implicit A: MeetSemilattice[A]) = new LatticeProperties( - name = "meetSemilattice", - parents = Nil, - join = None, - meet = Some(semilattice(A.meetSemilattice)), - 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)), - "absorption" -> forAll { (x: A, y: A) => - (A.join(x, A.meet(x, y)) ?== x) && (A.meet(x, A.join(x, y)) ?== x) - } - ) - - def distributiveLattice(implicit A: DistributiveLattice[A]) = new LatticeProperties( - name = "distributiveLattice", - parents = Seq(lattice), - join = Some(semilattice(A.joinSemilattice)), - meet = Some(semilattice(A.meetSemilattice)), - "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))) - } - ) - - def boundedJoinSemilattice(implicit A: BoundedJoinSemilattice[A]) = new LatticeProperties( - name = "boundedJoinSemilattice", - parents = Seq(joinSemilattice), - join = Some(boundedSemilattice(A.joinSemilattice)), - meet = None - ) +trait LatticeLaws[A] extends JoinSemilatticeLaws[A] with MeetSemilatticeLaws[A] { + override implicit def S: Lattice[A] - def boundedMeetSemilattice(implicit A: BoundedMeetSemilattice[A]) = new LatticeProperties( - name = "boundedMeetSemilattice", - parents = Seq(meetSemilattice), - join = None, - meet = Some(boundedSemilattice(A.meetSemilattice)) - ) - - 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)) - ) - - 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)) - ) - - 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)) - ) - - def boundedDistributiveLattice(implicit A: BoundedDistributiveLattice[A]) = new LatticeProperties( - name = "boundedLattice", - parents = Seq(boundedLattice, distributiveLattice), - join = Some(boundedSemilattice(A.joinSemilattice)), - meet = Some(boundedSemilattice(A.meetSemilattice)) - ) - - class LatticeProperties( - val name: String, - val parents: Seq[LatticeProperties], - val join: Option[GroupProperties], - val meet: Option[GroupProperties], - val props: (String, Prop)* - ) extends RuleSet { - private val _m = meet map { "meet" -> _ } - private val _j = join map { "join" -> _ } - - val bases = _m.toList ::: _j.toList - } + def absorption(x: A, y: A)(implicit E: Eq[A]): IsEq[Boolean] = + (E.eqv(S.join(x, S.meet(x, y)), x) && E.eqv(S.meet(x, S.join(x, y)), x)) <-> true +} +object LatticeLaws { + def apply[A](implicit ev: Lattice[A]): LatticeLaws[A] = + new LatticeLaws[A] { def S: Lattice[A] = ev } } diff --git a/laws/src/main/scala/algebra/laws/MeetSemilatticeLaws.scala b/laws/src/main/scala/algebra/laws/MeetSemilatticeLaws.scala new file mode 100644 index 00000000..3145fef1 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/MeetSemilatticeLaws.scala @@ -0,0 +1,14 @@ +package algebra +package laws + +import cats.kernel.laws._ +import algebra.lattice._ + +trait MeetSemilatticeLaws[A] extends SemilatticeLaws[A] { + override implicit def S: MeetSemilattice[A] +} + +object MeetSemilatticeLaws { + def apply[A](implicit ev: MeetSemilattice[A]): MeetSemilatticeLaws[A] = + new MeetSemilatticeLaws[A] { def S: MeetSemilattice[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeGroupLaws.scala b/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeGroupLaws.scala new file mode 100755 index 00000000..699948e9 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeGroupLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait MultiplicativeCommutativeGroupLaws[A] extends MultiplicativeGroupLaws[A] with MultiplicativeCommutativeMonoidLaws[A] { + override implicit def S: MultiplicativeCommutativeGroup[A] +} + +object MultiplicativeCommutativeGroupLaws { + def apply[A](implicit ev: MultiplicativeCommutativeGroup[A]): MultiplicativeCommutativeGroupLaws[A] = + new MultiplicativeCommutativeGroupLaws[A] { def S: MultiplicativeCommutativeGroup[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeMonoidLaws.scala b/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeMonoidLaws.scala new file mode 100755 index 00000000..854ee6e9 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeMonoidLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait MultiplicativeCommutativeMonoidLaws[A] extends MultiplicativeMonoidLaws[A] with MultiplicativeCommutativeSemigroupLaws[A] { + override implicit def S: MultiplicativeCommutativeMonoid[A] +} + +object MultiplicativeCommutativeMonoidLaws { + def apply[A](implicit ev: MultiplicativeCommutativeMonoid[A]): MultiplicativeCommutativeMonoidLaws[A] = + new MultiplicativeCommutativeMonoidLaws[A] { def S: MultiplicativeCommutativeMonoid[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeSemigroupLaws.scala b/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeSemigroupLaws.scala new file mode 100755 index 00000000..1c03fe24 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/MultiplicativeCommutativeSemigroupLaws.scala @@ -0,0 +1,18 @@ +package algebra +package laws + +import algebra.ring._ +import cats.kernel.laws._ + +trait MultiplicativeCommutativeSemigroupLaws[A] extends MultiplicativeSemigroupLaws[A] { + override implicit def S: MultiplicativeCommutativeSemigroup[A] + + def timesCommutative(x: A, y: A): IsEq[A] = + S.times(x, y) <-> S.times(y, x) + +} + +object MultiplicativeCommutativeSemigroupLaws { + def apply[A](implicit ev: MultiplicativeCommutativeSemigroup[A]): MultiplicativeCommutativeSemigroupLaws[A] = + new MultiplicativeCommutativeSemigroupLaws[A] { def S: MultiplicativeCommutativeSemigroup[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/MultiplicativeGroupLaws.scala b/laws/src/main/scala/algebra/laws/MultiplicativeGroupLaws.scala new file mode 100755 index 00000000..775046ec --- /dev/null +++ b/laws/src/main/scala/algebra/laws/MultiplicativeGroupLaws.scala @@ -0,0 +1,24 @@ +package algebra +package laws + +import algebra.ring._ +import cats.kernel.laws._ + +trait MultiplicativeGroupLaws[A] extends MultiplicativeMonoidLaws[A] { + override implicit def S: MultiplicativeGroup[A] + + def leftReciprocal(x: A): IsEq[A] = + S.times(S.reciprocal(x), x) <-> S.one + + def rightReciprocal(x: A): IsEq[A] = + S.times(x, S.reciprocal(x)) <-> S.one + + def consistentDiv(x: A, y: A): IsEq[A] = + S.div(x, y) <-> S.times(x, S.reciprocal(y)) + +} + +object MultiplicativeGroupLaws { + def apply[A](implicit ev: MultiplicativeGroup[A]): MultiplicativeGroupLaws[A] = + new MultiplicativeGroupLaws[A] { def S: MultiplicativeGroup[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/MultiplicativeMonoidLaws.scala b/laws/src/main/scala/algebra/laws/MultiplicativeMonoidLaws.scala new file mode 100755 index 00000000..76c1ec42 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/MultiplicativeMonoidLaws.scala @@ -0,0 +1,29 @@ +package algebra +package laws + +import algebra.ring._ +import cats.kernel.laws._ + +trait MultiplicativeMonoidLaws[A] extends MultiplicativeSemigroupLaws[A] { + override implicit def S: MultiplicativeMonoid[A] + + def leftOne(a: A): IsEq[A] = + S.times(S.one, a) <-> a + + def rightOne(a: A): IsEq[A] = + S.times(a, S.one) <-> a + + def pow0(a: A): IsEq[A] = + S.pow(a, 0) <-> S.one + + def product: IsEq[A] = + S.product(Nil) <-> S.one + + def isOne(a: A, eqv: Eq[A]): IsEq[Boolean] = + eqv.eqv(a, S.one) <-> S.isOne(a)(eqv) +} + +object MultiplicativeMonoidLaws { + def apply[A](implicit ev: MultiplicativeMonoid[A]): MultiplicativeMonoidLaws[A] = + new MultiplicativeMonoidLaws[A] { def S: MultiplicativeMonoid[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/MultiplicativeSemigroupLaws.scala b/laws/src/main/scala/algebra/laws/MultiplicativeSemigroupLaws.scala new file mode 100755 index 00000000..9d9693bc --- /dev/null +++ b/laws/src/main/scala/algebra/laws/MultiplicativeSemigroupLaws.scala @@ -0,0 +1,29 @@ +package algebra +package laws + +import algebra.ring._ +import cats.kernel.laws._ + +trait MultiplicativeSemigroupLaws[A] { + implicit def S: MultiplicativeSemigroup[A] + + def timesAssociative(x: A, y: A, z: A): IsEq[A] = + S.times(S.times(x, y), z) <-> S.times(x, S.times(y, z)) + + def pow1(a: A): IsEq[A] = + S.pow(a, 1) <-> a + + def pow2(a: A): IsEq[A] = + S.pow(a, 2) <-> S.times(a, a) + + def pow3(a: A): IsEq[A] = + S.pow(a, 3) <-> S.times(S.times(a, a), a) + + def tryProduct(xs: Vector[A]): IsEq[Option[A]] = + S.tryProduct(xs) <-> xs.reduceOption(S.times) +} + +object MultiplicativeSemigroupLaws { + def apply[A](implicit ev: MultiplicativeSemigroup[A]): MultiplicativeSemigroupLaws[A] = + new MultiplicativeSemigroupLaws[A] { def S: MultiplicativeSemigroup[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/RigLaws.scala b/laws/src/main/scala/algebra/laws/RigLaws.scala new file mode 100755 index 00000000..3dd19d6f --- /dev/null +++ b/laws/src/main/scala/algebra/laws/RigLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait RigLaws[A] extends SemiringLaws[A] with MultiplicativeMonoidLaws[A] { + override implicit def S: Rig[A] +} + +object RigLaws { + def apply[A](implicit ev: Rig[A]): RigLaws[A] = + new RigLaws[A] { def S: Rig[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/RingLaws.scala b/laws/src/main/scala/algebra/laws/RingLaws.scala index 307d13e8..407c4782 100644 --- a/laws/src/main/scala/algebra/laws/RingLaws.scala +++ b/laws/src/main/scala/algebra/laws/RingLaws.scala @@ -3,6 +3,16 @@ package laws import algebra.ring._ +trait RingLaws[A] extends RigLaws[A] with RngLaws[A] { + override implicit def S: Ring[A] +} + +object RingLaws { + def apply[A](implicit ev: Ring[A]): RingLaws[A] = + new RingLaws[A] { def S: Ring[A] = ev } +} +/* + import catalysts.Platform import cats.kernel.laws._ @@ -286,3 +296,4 @@ trait RingLaws[A] extends GroupLaws[A] { self => def bases = Seq("additive" -> al, "multiplicative" -> ml) } } +*/ diff --git a/laws/src/main/scala/algebra/laws/RngLaws.scala b/laws/src/main/scala/algebra/laws/RngLaws.scala new file mode 100755 index 00000000..a14e9de2 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/RngLaws.scala @@ -0,0 +1,13 @@ +package algebra +package laws + +import algebra.ring._ + +trait RngLaws[A] extends SemiringLaws[A] with AdditiveCommutativeGroupLaws[A] { + override implicit def S: Rng[A] +} + +object RngLaws { + def apply[A](implicit ev: Rng[A]): RngLaws[A] = + new RngLaws[A] { def S: Rng[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/SemiringLaws.scala b/laws/src/main/scala/algebra/laws/SemiringLaws.scala new file mode 100755 index 00000000..ab95ca2a --- /dev/null +++ b/laws/src/main/scala/algebra/laws/SemiringLaws.scala @@ -0,0 +1,26 @@ +package algebra +package laws + +import algebra.ring._ +import cats.kernel.laws._ + +trait SemiringLaws[A] extends AdditiveCommutativeMonoidLaws[A] with MultiplicativeSemigroupLaws[A] { + override implicit def S: Semiring[A] + + def leftDistributive(x: A, y: A, z: A): IsEq[A] = + S.times(x, S.plus(y, z)) <-> S.plus(S.times(x, y), S.times(x, z)) + + def rightDistributive(x: A, y: A, z: A): IsEq[A] = + S.times(S.plus(x, y), z) <-> S.plus(S.times(x, z), S.times(y, z)) + + def zeroLeftAnnihilates(a: A): IsEq[A] = + S.times(S.zero, a) <-> S.zero + + def zeroRightAnnihilates(a: A): IsEq[A] = + S.times(a, S.zero) <-> S.zero +} + +object SemiringLaws { + def apply[A](implicit ev: Semiring[A]): SemiringLaws[A] = + new SemiringLaws[A] { def S: Semiring[A] = ev } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeGroupTests.scala b/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeGroupTests.scala new file mode 100755 index 00000000..33bc2e1d --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeGroupTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait AdditiveCommutativeGroupTests[A] extends AdditiveCommutativeMonoidTests[A] with AdditiveGroupTests[A] { + def laws: AdditiveCommutativeGroupLaws[A] + + def additiveCommutativeGroup(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRuleSet = + new CommutativeRuleSet( + "additiveCommutativeGroup", + additiveGroup, + Some(additiveCommutativeMonoid) + ) +} + +object AdditiveCommutativeGroupTests { + def apply[A: AdditiveCommutativeGroup]: AdditiveCommutativeGroupTests[A] = + new AdditiveCommutativeGroupTests[A] { def laws: AdditiveCommutativeGroupLaws[A] = AdditiveCommutativeGroupLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeMonoidTests.scala b/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeMonoidTests.scala new file mode 100755 index 00000000..0fba6ec7 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeMonoidTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait AdditiveCommutativeMonoidTests[A] extends AdditiveCommutativeSemigroupTests[A] with AdditiveMonoidTests[A] { + def laws: AdditiveCommutativeMonoidLaws[A] + + def additiveCommutativeMonoid(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRuleSet = + new CommutativeRuleSet( + "additiveCommutativeMonoid", + additiveMonoid, + Some(additiveCommutativeSemigroup) + ) +} + +object AdditiveCommutativeMonoidTests { + def apply[A: AdditiveCommutativeMonoid]: AdditiveCommutativeMonoidTests[A] = + new AdditiveCommutativeMonoidTests[A] { def laws: AdditiveCommutativeMonoidLaws[A] = AdditiveCommutativeMonoidLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeSemigroupTests.scala b/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeSemigroupTests.scala new file mode 100755 index 00000000..b58cfdae --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/AdditiveCommutativeSemigroupTests.scala @@ -0,0 +1,25 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} +import Prop._ + +trait AdditiveCommutativeSemigroupTests[A] extends AdditiveSemigroupTests[A] with CommutativeTests { + + def laws: AdditiveCommutativeSemigroupLaws[A] + + def additiveCommutativeSemigroup(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRuleSet = + new CommutativeRuleSet( + "additiveCommutativeSemigroup", + additiveSemigroup, + None, + "plus commutative" -> forAll(laws.plusCommutative _) + ) +} + +object AdditiveCommutativeSemigroupTests { + def apply[A: AdditiveCommutativeSemigroup]: AdditiveCommutativeSemigroupTests[A] = + new AdditiveCommutativeSemigroupTests[A] { def laws: AdditiveCommutativeSemigroupLaws[A] = AdditiveCommutativeSemigroupLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/AdditiveGroupTests.scala b/laws/src/main/scala/algebra/laws/discipline/AdditiveGroupTests.scala new file mode 100755 index 00000000..e0eb0e8c --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/AdditiveGroupTests.scala @@ -0,0 +1,26 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary +import org.scalacheck.Prop.forAll + +trait AdditiveGroupTests[A] extends AdditiveMonoidTests[A] { + + def laws: AdditiveGroupLaws[A] + + def additiveGroup(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "additiveGroup", + Some(additiveMonoid), + "left negate" -> forAll(laws.leftNegate _), + "right negate" -> forAll(laws.rightNegate _), + "consistent minus" -> forAll(laws.consistentMinus _) + ) +} + +object AdditiveGroupTests { + def apply[A: AdditiveGroup]: AdditiveGroupTests[A] = + new AdditiveGroupTests[A] { def laws: AdditiveGroupLaws[A] = AdditiveGroupLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/AdditiveMonoidTests.scala b/laws/src/main/scala/algebra/laws/discipline/AdditiveMonoidTests.scala new file mode 100755 index 00000000..736f3ea6 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/AdditiveMonoidTests.scala @@ -0,0 +1,29 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} +import Prop._ +import cats.kernel.instances.boolean._ + +trait AdditiveMonoidTests[A] extends AdditiveSemigroupTests[A] { + + def laws: AdditiveMonoidLaws[A] + + def additiveMonoid(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "additiveMonoid", + Some(additiveSemigroup), + "left zero" -> forAll(laws.leftZero _), + "right zero" -> forAll(laws.rightZero _), + "sumN0" -> forAll(laws.sumN0 _), + "sumAll" -> laws.sumAll, + "isZero" -> forAll((a: A) => laws.isZero(a, eqA)) + ) +} + +object AdditiveMonoidTests { + def apply[A: AdditiveMonoid]: AdditiveMonoidTests[A] = + new AdditiveMonoidTests[A] { def laws: AdditiveMonoidLaws[A] = AdditiveMonoidLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/AdditiveSemigroupTests.scala b/laws/src/main/scala/algebra/laws/discipline/AdditiveSemigroupTests.scala new file mode 100755 index 00000000..9915c1cf --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/AdditiveSemigroupTests.scala @@ -0,0 +1,30 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} +import Prop._ +import org.typelevel.discipline.Laws +import cats.kernel.instances.option._ + +trait AdditiveSemigroupTests[A] extends Laws { + def laws: AdditiveSemigroupLaws[A] + + def additiveSemigroup(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "additiveSemigroup", + None, + "plus associative" -> forAll(laws.plusAssociative _), + "sumN1" -> forAll(laws.sumN1 _), + "sumN2" -> forAll(laws.sumN2 _), + "sumN3" -> forAll(laws.sumN3 _), + "trySum" -> forAll(laws.trySum _) + ) + +} + +object AdditiveSemigroupTests { + def apply[A: AdditiveSemigroup]: AdditiveSemigroupTests[A] = + new AdditiveSemigroupTests[A] { def laws: AdditiveSemigroupLaws[A] = AdditiveSemigroupLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/BoundedDistributiveLatticeTests.scala b/laws/src/main/scala/algebra/laws/discipline/BoundedDistributiveLatticeTests.scala new file mode 100644 index 00000000..45211a5e --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/BoundedDistributiveLatticeTests.scala @@ -0,0 +1,25 @@ +package algebra +package laws +package discipline + +import algebra.lattice.BoundedDistributiveLattice +import org.scalacheck.{Arbitrary, Prop} + +trait BoundedDistributiveLatticeTests[A] extends DistributiveLatticeTests[A] with BoundedLatticeTests[A] { + def laws: BoundedDistributiveLatticeLaws[A] + + def boundedDistributiveLattice(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new RuleSet { + def name: String = "boundedDistributiveLattice" + def bases: Seq[(String, RuleSet)] = Nil + def parents: Seq[RuleSet] = Seq(distributiveLattice, boundedLattice) + def props: Seq[(String, Prop)] = Nil + } +} + +object BoundedDistributiveLatticeTests { + def apply[A : BoundedDistributiveLattice]: BoundedDistributiveLatticeTests[A] = + new BoundedDistributiveLatticeTests[A] { + def laws: BoundedDistributiveLatticeLaws[A] = BoundedDistributiveLatticeLaws[A] + } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/BoundedJoinSemilatticeTests.scala b/laws/src/main/scala/algebra/laws/discipline/BoundedJoinSemilatticeTests.scala new file mode 100644 index 00000000..f7d58516 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/BoundedJoinSemilatticeTests.scala @@ -0,0 +1,24 @@ +package algebra +package laws +package discipline + +import algebra.lattice.BoundedJoinSemilattice +import cats.kernel.laws.discipline.BoundedSemilatticeTests +import org.scalacheck.{Arbitrary, Prop} + +trait BoundedJoinSemilatticeTests[A] extends BoundedSemilatticeTests[A] with JoinSemilatticeTests[A] { + def laws: BoundedJoinSemilatticeLaws[A] + + def boundedJoinSemilattice(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new RuleSet { + def name: String = "boundedJoinSemilattice" + def bases: Seq[(String, RuleSet)] = Nil + def parents: Seq[RuleSet] = Seq(boundedSemilattice, joinSemilattice) + def props: Seq[(String, Prop)] = Nil + } +} + +object BoundedJoinSemilatticeTests { + def apply[A : BoundedJoinSemilattice]: BoundedJoinSemilatticeTests[A] = + new BoundedJoinSemilatticeTests[A] { def laws: BoundedJoinSemilatticeLaws[A] = BoundedJoinSemilatticeLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/BoundedLatticeTests.scala b/laws/src/main/scala/algebra/laws/discipline/BoundedLatticeTests.scala new file mode 100644 index 00000000..81799ba7 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/BoundedLatticeTests.scala @@ -0,0 +1,27 @@ +package algebra +package laws +package discipline + +import algebra.lattice.BoundedLattice +import org.scalacheck.{Arbitrary, Prop} +import Prop.forAll +import cats.kernel.instances.boolean._ + +trait BoundedLatticeTests[A] extends LatticeTests[A] with BoundedJoinSemilatticeTests[A] with BoundedMeetSemilatticeTests[A] { + def laws: BoundedLatticeLaws[A] + + def boundedLattice(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new RuleSet { + def name: String = "boundedLattice" + def bases: Seq[(String, RuleSet)] = Nil + def parents: Seq[RuleSet] = Seq(lattice, boundedJoinSemilattice, boundedMeetSemilattice) + def props: Seq[(String, Prop)] = Seq( + "lattice absorption" -> forAll(laws.absorption _) + ) + } +} + +object BoundedLatticeTests { + def apply[A : BoundedLattice]: BoundedLatticeTests[A] = + new BoundedLatticeTests[A] { def laws: BoundedLatticeLaws[A] = BoundedLatticeLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/BoundedMeetSemilatticeTests.scala b/laws/src/main/scala/algebra/laws/discipline/BoundedMeetSemilatticeTests.scala new file mode 100644 index 00000000..39982176 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/BoundedMeetSemilatticeTests.scala @@ -0,0 +1,24 @@ +package algebra +package laws +package discipline + +import algebra.lattice.BoundedMeetSemilattice +import cats.kernel.laws.discipline.BoundedSemilatticeTests +import org.scalacheck.{Arbitrary, Prop} + +trait BoundedMeetSemilatticeTests[A] extends BoundedSemilatticeTests[A] with MeetSemilatticeTests[A] { + def laws: BoundedMeetSemilatticeLaws[A] + + def boundedMeetSemilattice(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new RuleSet { + def name: String = "boundedMeetSemilattice" + def bases: Seq[(String, RuleSet)] = Nil + def parents: Seq[RuleSet] = Seq(boundedSemilattice, meetSemilattice) + def props: Seq[(String, Prop)] = Nil + } +} + +object BoundedMeetSemilatticeTests { + def apply[A : BoundedMeetSemilattice]: BoundedMeetSemilatticeTests[A] = + new BoundedMeetSemilatticeTests[A] { def laws: BoundedMeetSemilatticeLaws[A] = BoundedMeetSemilatticeLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/CommutativeRigTests.scala b/laws/src/main/scala/algebra/laws/discipline/CommutativeRigTests.scala new file mode 100755 index 00000000..f0d91bdd --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/CommutativeRigTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait CommutativeRigTests[A] extends RigTests[A] with CommutativeSemiringTests[A] { + def laws: CommutativeRigLaws[A] + + def commutativeRig(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRingRuleSet = + new CommutativeRingRuleSet( + "commutativeRig", + rig, + Seq(commutativeSemiring) + ) +} + +object CommutativeRigTests { + def apply[A: CommutativeRig]: CommutativeRigTests[A] = + new CommutativeRigTests[A] { def laws: CommutativeRigLaws[A] = CommutativeRigLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/CommutativeRingTests.scala b/laws/src/main/scala/algebra/laws/discipline/CommutativeRingTests.scala new file mode 100755 index 00000000..d63be44b --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/CommutativeRingTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait CommutativeRingTests[A] extends RingTests[A] with CommutativeRigTests[A] with CommutativeRngTests[A] { + def laws: CommutativeRingLaws[A] + + def commutativeRing(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRingRuleSet = + new CommutativeRingRuleSet( + "commutativeRing", + rng, + Seq(commutativeRig, commutativeRng) + ) +} + +object CommutativeRingTests { + def apply[A: CommutativeRing]: CommutativeRingTests[A] = + new CommutativeRingTests[A] { def laws: CommutativeRingLaws[A] = CommutativeRingLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/CommutativeRngTests.scala b/laws/src/main/scala/algebra/laws/discipline/CommutativeRngTests.scala new file mode 100755 index 00000000..924376ed --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/CommutativeRngTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait CommutativeRngTests[A] extends RngTests[A] with CommutativeSemiringTests[A] { + def laws: CommutativeRngLaws[A] + + def commutativeRng(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRingRuleSet = + new CommutativeRingRuleSet( + "commutativeRng", + rng, + Seq(commutativeSemiring) + ) +} + +object CommutativeRngTests { + def apply[A: CommutativeRng]: CommutativeRngTests[A] = + new CommutativeRngTests[A] { def laws: CommutativeRngLaws[A] = CommutativeRngLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/CommutativeSemiringTests.scala b/laws/src/main/scala/algebra/laws/discipline/CommutativeSemiringTests.scala new file mode 100755 index 00000000..69cc8192 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/CommutativeSemiringTests.scala @@ -0,0 +1,31 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} + +trait CommutativeSemiringTests[A] extends SemiringTests[A] with MultiplicativeCommutativeSemigroupTests[A] { + def laws: CommutativeSemiringLaws[A] + + def commutativeSemiring(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRingRuleSet = + new CommutativeRingRuleSet( + "commutativeSemiring", + semiring, + Nil + ) + + class CommutativeRingRuleSet(val name: String, + val noncommutativeParent: RingRuleSet, + val commutativeParents: Seq[CommutativeRingRuleSet], + val props: (String, Prop)* + ) extends RuleSet { + def bases = Nil + val parents = Seq(noncommutativeParent) ++ commutativeParents + } +} + +object CommutativeSemiringTests { + def apply[A: CommutativeSemiring]: CommutativeSemiringTests[A] = + new CommutativeSemiringTests[A] { def laws: CommutativeSemiringLaws[A] = CommutativeSemiringLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/CommutativeTests.scala b/laws/src/main/scala/algebra/laws/discipline/CommutativeTests.scala new file mode 100644 index 00000000..238c1ff5 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/CommutativeTests.scala @@ -0,0 +1,16 @@ +package algebra.laws.discipline + +import org.typelevel.discipline.Laws +import org.scalacheck.Prop + +trait CommutativeTests { self: Laws => + + class CommutativeRuleSet(val name: String, + val noncommutativeParent: RuleSet, + val commutativeParent: Option[CommutativeRuleSet], + val props: (String, Prop)* + ) extends RuleSet { + val parents = Seq(noncommutativeParent) ++ commutativeParent.toSeq + val bases = Nil + } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/DistributiveLatticeTests.scala b/laws/src/main/scala/algebra/laws/discipline/DistributiveLatticeTests.scala new file mode 100644 index 00000000..bc4f7698 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/DistributiveLatticeTests.scala @@ -0,0 +1,24 @@ +package algebra +package laws +package discipline + +import algebra.lattice.DistributiveLattice +import org.scalacheck.Arbitrary +import org.scalacheck.Prop.forAll +import cats.kernel.instances.boolean._ + +trait DistributiveLatticeTests[A] extends LatticeTests[A] { + def laws: DistributiveLatticeLaws[A] + + def distributiveLattice(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "distributiveLattice", + Some(lattice), + "distributiveLattice distribute" -> forAll(laws.distributive _) + ) +} + +object DistributiveLatticeTests { + def apply[A : DistributiveLattice]: DistributiveLatticeTests[A] = + new DistributiveLatticeTests[A] { def laws: DistributiveLatticeLaws[A] = DistributiveLatticeLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/FieldTests.scala b/laws/src/main/scala/algebra/laws/discipline/FieldTests.scala new file mode 100755 index 00000000..bb2a3a0d --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/FieldTests.scala @@ -0,0 +1,23 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait FieldTests[A] extends CommutativeRingTests[A] with MultiplicativeCommutativeGroupTests[A] { + def laws: FieldLaws[A] + + def field(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new RuleSet { + def name = "field" + def parents = Seq(commutativeRing, multiplicativeCommutativeGroup) + def bases = Nil + def props = Nil + } +} + +object FieldTests { + def apply[A: Field]: FieldTests[A] = + new FieldTests[A] { def laws: FieldLaws[A] = FieldLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/JoinSemilatticeTests.scala b/laws/src/main/scala/algebra/laws/discipline/JoinSemilatticeTests.scala new file mode 100644 index 00000000..8c061fd9 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/JoinSemilatticeTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.lattice.JoinSemilattice +import cats.kernel.laws.discipline.SemilatticeTests +import org.scalacheck.Arbitrary + +trait JoinSemilatticeTests[A] extends SemilatticeTests[A] { + def laws: JoinSemilatticeLaws[A] + + def joinSemilattice(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "joinSemilattice", + Some(semilattice) + ) +} + +object JoinSemilatticeTests { + def apply[A : JoinSemilattice]: JoinSemilatticeTests[A] = + new JoinSemilatticeTests[A] { def laws: JoinSemilatticeLaws[A] = JoinSemilatticeLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/LatticeTests.scala b/laws/src/main/scala/algebra/laws/discipline/LatticeTests.scala new file mode 100644 index 00000000..ad98254d --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/LatticeTests.scala @@ -0,0 +1,27 @@ +package algebra +package laws +package discipline + +import algebra.lattice.Lattice +import org.scalacheck.{Arbitrary, Prop} +import Prop.forAll +import cats.kernel.instances.boolean._ + +trait LatticeTests[A] extends JoinSemilatticeTests[A] with MeetSemilatticeTests[A] { + def laws: LatticeLaws[A] + + def lattice(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new RuleSet { + def name: String = "lattice" + def bases: Seq[(String, RuleSet)] = Nil + def parents: Seq[RuleSet] = Seq(joinSemilattice, meetSemilattice) + def props: Seq[(String, Prop)] = Seq( + "lattice absorption" -> forAll(laws.absorption _) + ) + } +} + +object LatticeTests { + def apply[A : Lattice]: LatticeTests[A] = + new LatticeTests[A] { def laws: LatticeLaws[A] = LatticeLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/MeetSemilatticeTests.scala b/laws/src/main/scala/algebra/laws/discipline/MeetSemilatticeTests.scala new file mode 100644 index 00000000..ac75a6f4 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/MeetSemilatticeTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.lattice.MeetSemilattice +import cats.kernel.laws.discipline.SemilatticeTests +import org.scalacheck.Arbitrary + +trait MeetSemilatticeTests[A] extends SemilatticeTests[A] { + def laws: MeetSemilatticeLaws[A] + + def meetSemilattice(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "meetSemilattice", + Some(semilattice) + ) +} + +object MeetSemilatticeTests { + def apply[A : MeetSemilattice]: MeetSemilatticeTests[A] = + new MeetSemilatticeTests[A] { def laws: MeetSemilatticeLaws[A] = MeetSemilatticeLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeGroupTests.scala b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeGroupTests.scala new file mode 100755 index 00000000..08c2c860 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeGroupTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait MultiplicativeCommutativeGroupTests[A] extends MultiplicativeCommutativeMonoidTests[A] with MultiplicativeGroupTests[A] { + def laws: MultiplicativeCommutativeGroupLaws[A] + + def multiplicativeCommutativeGroup(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRuleSet = + new CommutativeRuleSet( + "multiplicativeCommutativeGroup", + multiplicativeGroup, + Some(multiplicativeCommutativeMonoid) + ) +} + +object MultiplicativeCommutativeGroupTests { + def apply[A: MultiplicativeCommutativeGroup]: MultiplicativeCommutativeGroupTests[A] = + new MultiplicativeCommutativeGroupTests[A] { def laws: MultiplicativeCommutativeGroupLaws[A] = MultiplicativeCommutativeGroupLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeMonoidTests.scala b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeMonoidTests.scala new file mode 100755 index 00000000..299ab95a --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeMonoidTests.scala @@ -0,0 +1,22 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait MultiplicativeCommutativeMonoidTests[A] extends MultiplicativeCommutativeSemigroupTests[A] with MultiplicativeMonoidTests[A] { + def laws: MultiplicativeCommutativeMonoidLaws[A] + + def multiplicativeCommutativeMonoid(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRuleSet = + new CommutativeRuleSet( + "multiplicativeCommutativeMonoid", + multiplicativeMonoid, + Some(multiplicativeCommutativeSemigroup) + ) +} + +object MultiplicativeCommutativeMonoidTests { + def apply[A: MultiplicativeCommutativeMonoid]: MultiplicativeCommutativeMonoidTests[A] = + new MultiplicativeCommutativeMonoidTests[A] { def laws: MultiplicativeCommutativeMonoidLaws[A] = MultiplicativeCommutativeMonoidLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeSemigroupTests.scala b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeSemigroupTests.scala new file mode 100755 index 00000000..8830f7f4 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeCommutativeSemigroupTests.scala @@ -0,0 +1,25 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} +import Prop._ + +trait MultiplicativeCommutativeSemigroupTests[A] extends MultiplicativeSemigroupTests[A] with CommutativeTests { + + def laws: MultiplicativeCommutativeSemigroupLaws[A] + + def multiplicativeCommutativeSemigroup(implicit arbA: Arbitrary[A], eqA: Eq[A]): CommutativeRuleSet = + new CommutativeRuleSet( + "multiplicativeCommutativeSemigroup", + multiplicativeSemigroup, + None, + "times commutative" -> forAll(laws.timesCommutative _) + ) +} + +object MultiplicativeCommutativeSemigroupTests { + def apply[A: MultiplicativeCommutativeSemigroup]: MultiplicativeCommutativeSemigroupTests[A] = + new MultiplicativeCommutativeSemigroupTests[A] { def laws: MultiplicativeCommutativeSemigroupLaws[A] = MultiplicativeCommutativeSemigroupLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/MultiplicativeGroupTests.scala b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeGroupTests.scala new file mode 100755 index 00000000..12bcaa39 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeGroupTests.scala @@ -0,0 +1,26 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} +import Prop._ + +trait MultiplicativeGroupTests[A] extends MultiplicativeMonoidTests[A] { + + def laws: MultiplicativeGroupLaws[A] + + def multiplicativeGroup(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "multiplicativeGroup", + Some(multiplicativeMonoid), + "left reciprocal" -> forAll(laws.leftReciprocal _), + "right reciprocal" -> forAll(laws.rightReciprocal _), + "consistent div" -> forAll(laws.consistentDiv _) + ) +} + +object MultiplicativeGroupTests { + def apply[A: MultiplicativeGroup]: MultiplicativeGroupTests[A] = + new MultiplicativeGroupTests[A] { def laws: MultiplicativeGroupLaws[A] = MultiplicativeGroupLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/MultiplicativeMonoidTests.scala b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeMonoidTests.scala new file mode 100755 index 00000000..0391aeef --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeMonoidTests.scala @@ -0,0 +1,29 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} +import Prop._ +import cats.kernel.instances.boolean._ + +trait MultiplicativeMonoidTests[A] extends MultiplicativeSemigroupTests[A] { + + def laws: MultiplicativeMonoidLaws[A] + + def multiplicativeMonoid(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "multiplicativeMonoid", + Some(multiplicativeSemigroup), + "left one" -> forAll(laws.leftOne _), + "right one" -> forAll(laws.rightOne _), + "pow0" -> forAll(laws.pow0 _), + "product" -> laws.product, + "isOne" -> forAll((a: A) => laws.isOne(a, eqA)) + ) +} + +object MultiplicativeMonoidTests { + def apply[A: MultiplicativeMonoid]: MultiplicativeMonoidTests[A] = + new MultiplicativeMonoidTests[A] { def laws: MultiplicativeMonoidLaws[A] = MultiplicativeMonoidLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/MultiplicativeSemigroupTests.scala b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeSemigroupTests.scala new file mode 100755 index 00000000..22ffa270 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/MultiplicativeSemigroupTests.scala @@ -0,0 +1,30 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} +import org.typelevel.discipline.Laws +import Prop._ +import cats.kernel.instances.option._ + +trait MultiplicativeSemigroupTests[A] extends Laws { + def laws: MultiplicativeSemigroupLaws[A] + + def multiplicativeSemigroup(implicit arbA: Arbitrary[A], eqA: Eq[A]): RuleSet = + new DefaultRuleSet( + "multiplicativeSemigroup", + None, + "times associative" -> forAll(laws.timesAssociative _), + "pow1" -> forAll(laws.pow1 _), + "pow2" -> forAll(laws.pow2 _), + "pow3" -> forAll(laws.pow3 _), + "tryProduct" -> forAll(laws.tryProduct _) + ) + +} + +object MultiplicativeSemigroupTests { + def apply[A: MultiplicativeSemigroup]: MultiplicativeSemigroupTests[A] = + new MultiplicativeSemigroupTests[A] { def laws: MultiplicativeSemigroupLaws[A] = MultiplicativeSemigroupLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/RigTests.scala b/laws/src/main/scala/algebra/laws/discipline/RigTests.scala new file mode 100755 index 00000000..4883e06d --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/RigTests.scala @@ -0,0 +1,23 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.Arbitrary + +trait RigTests[A] extends SemiringTests[A] with MultiplicativeMonoidTests[A] { + def laws: RigLaws[A] + + def rig(implicit arbA: Arbitrary[A], eqA: Eq[A]): RingRuleSet = + new RingRuleSet( + "rig", + additiveCommutativeMonoid, + multiplicativeMonoid, + Seq(semiring) + ) +} + +object RigTests { + def apply[A: Rig]: RigTests[A] = + new RigTests[A] { def laws: RigLaws[A] = RigLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/RingTests.scala b/laws/src/main/scala/algebra/laws/discipline/RingTests.scala new file mode 100755 index 00000000..209a3456 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/RingTests.scala @@ -0,0 +1,23 @@ +package algebra.laws.discipline + +import algebra.laws.RingLaws +import algebra.ring.Ring +import cats.kernel.Eq +import org.scalacheck.Arbitrary + +trait RingTests[A] extends RigTests[A] with RngTests[A] { + def laws: RingLaws[A] + + def ring(implicit arbA: Arbitrary[A], eqA: Eq[A]): RingRuleSet = + new RingRuleSet( + "ring", + additiveCommutativeGroup, + multiplicativeMonoid, + Seq(rig, rng) + ) +} + +object RingTests { + def apply[A: Ring]: RingTests[A] = + new RingTests[A] { def laws: RingLaws[A] = RingLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/RngTests.scala b/laws/src/main/scala/algebra/laws/discipline/RngTests.scala new file mode 100755 index 00000000..2e766071 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/RngTests.scala @@ -0,0 +1,23 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary} + +trait RngTests[A] extends SemiringTests[A] with AdditiveCommutativeGroupTests[A] { + def laws: RngLaws[A] + + def rng(implicit arbA: Arbitrary[A], eqA: Eq[A]): RingRuleSet = + new RingRuleSet( + "rng", + additiveCommutativeGroup, + multiplicativeSemigroup, + Seq(semiring) + ) +} + +object RngTests { + def apply[A: Rng]: RngTests[A] = + new RngTests[A] { def laws: RngLaws[A] = RngLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/SemiringTests.scala b/laws/src/main/scala/algebra/laws/discipline/SemiringTests.scala new file mode 100755 index 00000000..08eb8421 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/SemiringTests.scala @@ -0,0 +1,39 @@ +package algebra +package laws +package discipline + +import algebra.ring._ +import org.scalacheck.{Arbitrary, Prop} +import Prop._ + +trait SemiringTests[A] extends AdditiveCommutativeMonoidTests[A] with MultiplicativeSemigroupTests[A] { + def laws: SemiringLaws[A] + + def semiring(implicit arbA: Arbitrary[A], eqA: Eq[A]): RingRuleSet = + new RingRuleSet( + "semiring", + additiveCommutativeMonoid, + multiplicativeSemigroup, + Nil, + "left distributive" -> forAll(laws.leftDistributive _), + "right distributive" -> forAll(laws.rightDistributive _), + "zero left annihilates" -> forAll(laws.zeroLeftAnnihilates _), + "zero right annihilates" -> forAll(laws.zeroRightAnnihilates _) + ) + + class RingRuleSet( + val name: String, + val additiveRuleSet: RuleSet, + val multiplicativeRuleSet: RuleSet, + val additionalParents: Seq[RingRuleSet], + val props: (String, Prop)* + ) extends RuleSet { + def parents = additionalParents ++ Seq(additiveRuleSet, multiplicativeRuleSet) + def bases = Nil + } +} + +object SemiringTests { + def apply[A: Semiring]: SemiringTests[A] = + new SemiringTests[A] { def laws: SemiringLaws[A] = SemiringLaws[A] } +} diff --git a/laws/src/main/scala/algebra/laws/discipline/package.scala b/laws/src/main/scala/algebra/laws/discipline/package.scala new file mode 100644 index 00000000..e7e904e3 --- /dev/null +++ b/laws/src/main/scala/algebra/laws/discipline/package.scala @@ -0,0 +1,11 @@ +package algebra.laws + +import cats.kernel.Eq +import cats.kernel.laws.IsEq +import org.scalacheck.Prop + +package object discipline { + + implicit def catsLawsIsEqToProp[A: Eq](isEq: IsEq[A]): Prop = + cats.kernel.laws.discipline.catsLawsIsEqToProp[A](isEq) +} diff --git a/laws/src/test/scala/algebra/laws/LawTests.scala b/laws/src/test/scala/algebra/laws/LawTests.scala index a0513502..ec909799 100644 --- a/laws/src/test/scala/algebra/laws/LawTests.scala +++ b/laws/src/test/scala/algebra/laws/LawTests.scala @@ -38,8 +38,8 @@ class LawTests extends FunSuite with Configuration with Discipline { implicit val byteLattice: Lattice[Byte] = ByteMinMaxLattice implicit val shortLattice: Lattice[Short] = ShortMinMaxLattice - implicit val intLattice: BoundedDistributiveLattice[Int] = IntMinMaxLattice - implicit val longLattice: BoundedDistributiveLattice[Long] = LongMinMaxLattice + implicit val intLattice: BoundedDistributiveLatticeLaws[Int] = IntMinMaxLattice + implicit val longLattice: BoundedDistributiveLatticeLaws[Long] = LongMinMaxLattice implicit def orderLaws[A: Cogen: Eq: Arbitrary] = OrderLaws[A] implicit def groupLaws[A: Eq: Arbitrary] = GroupLaws[A]