Last active
December 26, 2017 06:04
-
-
Save yasuabe/a5cfff487d65a5ed0cc27418eb7d8e3b to your computer and use it in GitHub Desktop.
property(redefine+cats+scalacheck)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ratio1 | |
import cats.Apply | |
import cats.instances.int._ | |
import cats.syntax.all._ | |
import eu.timepit.refined.cats._ | |
import eu.timepit.refined.refineMV | |
import eu.timepit.refined.scalacheck.numeric.chooseRefinedNum | |
import org.scalacheck.Gen._ | |
import org.scalacheck.Prop.forAll | |
import org.scalacheck.{Arbitrary, Gen, Prop, Properties} | |
import ratio1.Rational._ | |
trait Helper { | |
implicit val genApply: Apply[Gen] = new Apply[Gen] { | |
override def ap[A, B] (gf: Gen[A => B])(ga: Gen[A]): Gen[B] = gf flatMap ga.map | |
override def map[A, B](ga: Gen[A]) (f: A => B): Gen[B] = ga map f | |
} | |
def double[A](ga: Gen[A]): Gen[(A, A)] = (ga, ga).mapN((_, _)) | |
def triple[A](ga: Gen[A]): Gen[(A, A, A)] = (ga, ga, ga).mapN((_, _, _)) | |
val lower: NonZeroInt = refineMV[NonZero](-10) | |
val upper: NonZeroInt = refineMV[NonZero](10) | |
val genNZInt: Gen[NonZeroInt] = chooseRefinedNum(lower, upper) | |
implicit val arbNonZeroInt: Arbitrary[NonZeroInt] = Arbitrary(genNZInt) | |
val intGen: Gen[Int] = chooseNum(-100, 100) | |
val nzIntGen: Gen[NonZeroInt] = | |
chooseRefinedNum(refineMV[NonZero](-100), refineMV[NonZero](100)) | |
} | |
object NonZeroIntSpec extends Properties("NonZeroInt") with Helper { | |
import NonZeroInt.one | |
property("Group: communitativity") = forAll(double(genNZInt)) { case (n1, n2) => | |
n1 * n2 === n2 * n1 | |
} | |
property("Group: associativity") = forAll(triple(genNZInt)) { case (n1, n2, n3) => | |
(n1 * n2) * n3 === n1 * (n2 * n3) | |
} | |
property("Group: identity element") = forAll(genNZInt) { n1 => | |
one * n1 === one * n1 && one * n1 === n1 | |
} | |
} | |
object RationalSpec extends Properties("Rational") with Helper { | |
val gen: Gen[Rational] = (intGen, nzIntGen).mapN(Rational(_, _)) | |
property("Rational: equality") = forAll(nzIntGen, intGen, nzIntGen) { (m, n, d) => | |
Rational(n, d) === Rational(n * m.value, d * m) | |
} | |
property("Group: communitativity") = forAll(double(gen)) { case (r1, r2) => | |
r1 + r2 == r2 + r1 | |
} | |
property("Group: associativity") = forAll(triple(gen)) { case (r1, r2, r3) => | |
(r1 + r2) + r3 == r1 + (r2 + r3) | |
} | |
property("Group: identity element") = forAll(gen) { r1 => | |
zero + r1 == zero + r1 && zero + r1 === r1 | |
} | |
property("Group: inverse element") = forAll(gen) { r1 => | |
val inv = r1.negate | |
r1 + inv === inv + r1 && inv + r1 === zero | |
} | |
property("Ring: communitativity") = forAll(double(gen)) { case (r1, r2) => | |
r1 * r2 == r2 * r1 | |
} | |
property("Ring: associativity") = forAll(triple(gen)) { case (r1, r2, r3) => | |
(r1 * r2) * r3 == r1 * (r2 * r3) | |
} | |
property("Ring: unity") = forAll(gen) { r1 => | |
one * r1 === one * r1 && one * r1 === r1 | |
} | |
property("Ring: distributivity(1)") = forAll(triple(gen)) { case (r1, r2, r3) => | |
r1 * (r2 + r3) == r1 * r2 + r1 * r3 | |
} | |
property("Ring: distributivity(2)") = forAll(triple(gen)) { case (r1, r2, r3) => | |
(r1 + r2) * r3 == r1 * r3 + r2 * r3 | |
} | |
property("Field: inverse element") = forAll(gen.suchThat(_ =!= zero)) { r => | |
val inv = r.invert.toOption.get | |
r * inv === inv * r && inv * r === one | |
} | |
property("Field: inverse zero has no value") = Prop { | |
zero.invert.isLeft | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment