/scalacheck-binding/src/main/scala/scalaz/scalacheck/ScalazProperties.scala
Scala | 776 lines | 617 code | 154 blank | 5 comment | 1 complexity | 5fadb86513d9689313b2539e15d1ae15 MD5 | raw file
1package scalaz 2package scalacheck 3 4import org.scalacheck._ 5import Prop.forAll 6import Scalaz._ 7 8/** 9 * Scalacheck properties that should hold for instances of type classes defined in Scalaz Core. 10 */ 11object ScalazProperties { 12 private def newProperties(name: String)(f: Properties => Unit): Properties = { 13 val p = new Properties(name) 14 f(p) 15 p 16 } 17 18 object equal { 19 def commutativity[A](implicit A: Equal[A], arb: Arbitrary[A]): Prop = forAll(A.equalLaw.commutative _) 20 21 def reflexive[A](implicit A: Equal[A], arb: Arbitrary[A]): Prop = forAll(A.equalLaw.reflexive _) 22 23 def transitive[A](implicit A: Equal[A], arb: Arbitrary[A]): Prop = forAll(A.equalLaw.transitive _) 24 25 def naturality[A](implicit A: Equal[A], arb: Arbitrary[A]): Prop = forAll(A.equalLaw.naturality _) 26 27 def laws[A](implicit A: Equal[A], arb: Arbitrary[A]): Properties = 28 newProperties("equal") { p => 29 p.property("commutativity") = commutativity[A] 30 p.property("reflexive") = reflexive[A] 31 p.property("transitive") = transitive[A] 32 p.property("naturality") = naturality[A] 33 } 34 } 35 36 object order { 37 def antisymmetric[A](implicit A: Order[A], arb: Arbitrary[A]): Prop = 38 forAll(A.orderLaw.antisymmetric _) 39 40 def transitiveOrder[A](implicit A: Order[A], arb: Arbitrary[A]): Prop = forAll(A.orderLaw.transitiveOrder _) 41 42 def orderAndEqualConsistent[A](implicit A: Order[A], arb: Arbitrary[A]): Prop = forAll(A.orderLaw.orderAndEqualConsistent _) 43 44 import scala.math.{Ordering => SOrdering} 45 46 def scalaOrdering[A: Order: SOrdering: Arbitrary]: Prop = forAll((a1: A, a2: A) => Order[A].order(a1, a2) == Ordering.fromInt(SOrdering[A].compare(a1, a2))) 47 48 def laws[A](implicit A: Order[A], arb: Arbitrary[A]): Properties = 49 newProperties("order") { p => 50 p.include(equal.laws[A]) 51 p.property("antisymmetric") = antisymmetric[A] 52 p.property("transitive order") = transitiveOrder[A] 53 p.property("order and equal consistent") = orderAndEqualConsistent[A] 54 } 55 } 56 57 object `enum` { 58 def succpred[A](implicit A: Enum[A], arb: Arbitrary[A]): Prop = forAll(A.enumLaw.succpred _) 59 60 def predsucc[A](implicit A: Enum[A], arb: Arbitrary[A]): Prop = forAll(A.enumLaw.predsucc _) 61 62 def minmaxpred[A](implicit A: Enum[A]): Prop = A.enumLaw.minmaxpred 63 64 def minmaxsucc[A](implicit A: Enum[A]): Prop = A.enumLaw.minmaxsucc 65 66 private[this] val smallInt = Gen.choose(-100, 100) 67 68 def succn[A](implicit A: Enum[A], arb: Arbitrary[A]): Prop = forAll((x: A) => forAll(smallInt)(A.enumLaw.succn(x, _))) 69 70 def predn[A](implicit A: Enum[A], arb: Arbitrary[A]): Prop = forAll((x: A) => forAll(smallInt)(A.enumLaw.predn(x, _))) 71 72 def succorder[A](implicit A: Enum[A], arb: Arbitrary[A]): Prop = forAll(A.enumLaw.succorder _) 73 74 def predorder[A](implicit A: Enum[A], arb: Arbitrary[A]): Prop = forAll(A.enumLaw.predorder _) 75 76 def laws[A](implicit A: Enum[A], arb: Arbitrary[A]): Properties = 77 newProperties("enum") { p => 78 p.include(order.laws[A]) 79 p.property("predecessor then successor is identity") = succpred[A] 80 p.property("successor then predecessor is identity") = predsucc[A] 81 p.property("predecessor of the min is the max") = minmaxpred[A] 82 p.property("successor of the max is the min") = minmaxsucc[A] 83 p.property("n-successor is n-times successor") = succn[A] 84 p.property("n-predecessor is n-times predecessor") = predn[A] 85 p.property("successor is greater or equal") = succorder[A] 86 p.property("predecessor is less or equal") = predorder[A] 87 } 88 } 89 90 object semigroup { 91 import ScalazArbitrary.Arbitrary_Maybe 92 93 def associative[A](implicit A: Semigroup[A], eqa: Equal[A], arb: Arbitrary[A]): Prop = forAll(A.semigroupLaw.associative _) 94 95 def unfoldlSumOptConsistency[A, S](implicit A: Semigroup[A], eqa: Equal[A], aa: Arbitrary[A], as: Arbitrary[S], cs: Cogen[S]): Prop = 96 forAll(A.semigroupLaw.unfoldlSumOptConsistency[S] _) 97 98 def unfoldrSumOptConsistency[A, S](implicit A: Semigroup[A], eqa: Equal[A], aa: Arbitrary[A], as: Arbitrary[S], cs: Cogen[S]): Prop = 99 forAll(A.semigroupLaw.unfoldrSumOptConsistency[S] _) 100 101 def laws[A](implicit A: Semigroup[A], eqa: Equal[A], arb: Arbitrary[A]): Properties = 102 newProperties("semigroup") { p => 103 p.property("associative") = associative[A] 104 p.property("unfoldlSumOpt consistency") = unfoldlSumOptConsistency[A, Int] 105 p.property("unfoldrSumOpt consistency") = unfoldrSumOptConsistency[A, Int] 106 } 107 } 108 109 object monoid { 110 def leftIdentity[A](implicit A: Monoid[A], eqa: Equal[A], arb: Arbitrary[A]): Prop = forAll(A.monoidLaw.leftIdentity _) 111 112 def rightIdentity[A](implicit A: Monoid[A], eqa: Equal[A], arb: Arbitrary[A]): Prop = forAll(A.monoidLaw.rightIdentity _) 113 114 def laws[A](implicit A: Monoid[A], eqa: Equal[A], arb: Arbitrary[A]): Properties = 115 newProperties("monoid") { p => 116 p.include(semigroup.laws[A]) 117 p.property("left identity") = leftIdentity[A] 118 p.property("right identity") = rightIdentity[A] 119 } 120 } 121 122 object band { 123 def idempotency[A: Equal: Arbitrary](implicit A: Band[A]): Prop = 124 forAll(A.bandLaw.idempotency _) 125 126 def laws[A: Equal: Arbitrary](implicit A: Band[A]): Properties = 127 newProperties("band") { p => 128 p.include(semigroup.laws[A]) 129 p.property("idempotency") = idempotency[A] 130 } 131 } 132 133 object semilattice { 134 def commutative[A](implicit A: SemiLattice[A], eq: Equal[A], arb: Arbitrary[A]): Prop = forAll(A.semiLatticeLaw.commutative _) 135 136 def laws[A: Equal: Arbitrary](implicit A: SemiLattice[A]): Properties = 137 newProperties("semilattice") { p => 138 p.include(band.laws[A]) 139 p.property("commutative") = commutative[A] 140 } 141 } 142 143 object reducer { 144 import ScalazArbitrary.Arbitrary_Maybe 145 146 def consCorrectness[C, M](implicit R: Reducer[C, M], ac: Arbitrary[C], am: Arbitrary[M], eqm: Equal[M]): Prop = 147 forAll(R.reducerLaw.consCorrectness _) 148 149 def snocCorrectness[C, M](implicit R: Reducer[C, M], ac: Arbitrary[C], am: Arbitrary[M], eqm: Equal[M]): Prop = 150 forAll(R.reducerLaw.snocCorrectness _) 151 152 def unfoldlOptConsistency[C, M, S](implicit R: Reducer[C, M], ac: Arbitrary[C], as: Arbitrary[S], cs: Cogen[S], eqm: Equal[M]): Prop = 153 forAll(R.reducerLaw.unfoldlOptConsistency[S] _) 154 155 def unfoldrOptConsistency[C, M, S](implicit R: Reducer[C, M], ac: Arbitrary[C], as: Arbitrary[S], cs: Cogen[S], eqm: Equal[M]): Prop = 156 forAll(R.reducerLaw.unfoldrOptConsistency[S] _) 157 158 def laws[C: Arbitrary, M: Arbitrary: Equal](implicit R: Reducer[C, M]): Properties = 159 newProperties("reducer") { p => 160 p.property("cons correctness") = consCorrectness[C, M] 161 p.property("snoc correctness") = snocCorrectness[C, M] 162 p.property("unfoldlOpt consistency") = unfoldlOptConsistency[C, M, Int] 163 p.property("unfoldrOpt consistency") = unfoldrOptConsistency[C, M, Int] 164 } 165 } 166 167 object invariantFunctor { 168 def identity[F[_], X](implicit F: InvariantFunctor[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 169 forAll(F.invariantFunctorLaw.invariantIdentity[X] _) 170 171 def composite[F[_], X, Y, Z](implicit F: InvariantFunctor[F], af: Arbitrary[F[X]], axy: Arbitrary[(X => Y)], 172 ayz: Arbitrary[(Y => Z)], ayx: Arbitrary[(Y => X)], azy: Arbitrary[(Z => Y)], ef: Equal[F[Z]]): Prop = 173 forAll(F.invariantFunctorLaw.invariantComposite[X, Y, Z] _) 174 175 def laws[F[_]](implicit F: InvariantFunctor[F], af: Arbitrary[F[Int]], axy: Arbitrary[(Int => Int)], 176 ef: Equal[F[Int]]): Properties = 177 newProperties("invariantFunctor") { p => 178 p.property("identity") = identity[F, Int] 179 p.property("composite") = composite[F, Int, Int, Int] 180 } 181 } 182 183 object functor { 184 def identity[F[_], X](implicit F: Functor[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 185 forAll(F.functorLaw.identity[X] _) 186 187 def composite[F[_], X, Y, Z](implicit F: Functor[F], af: Arbitrary[F[X]], axy: Arbitrary[(X => Y)], 188 ayz: Arbitrary[(Y => Z)], ef: Equal[F[Z]]): Prop = 189 forAll(F.functorLaw.composite[X, Y, Z] _) 190 191 def laws[F[_]](implicit F: Functor[F], af: Arbitrary[F[Int]], axy: Arbitrary[(Int => Int)], 192 ef: Equal[F[Int]]): Properties = 193 newProperties("functor") { p => 194 p.include(invariantFunctor.laws[F]) 195 p.property("identity") = identity[F, Int] 196 p.property("composite") = composite[F, Int, Int, Int] 197 } 198 } 199 200 object profunctor { 201 def identity[M[_,_], A, B](implicit M: Profunctor[M], mba: Arbitrary[M[A, B]], ef: Equal[M[A,B]]): Prop = 202 forAll(M.profunctorLaw.identity[A, B] _) 203 204 def compose[M[_,_], A, B, C, D, E, F](implicit M: Profunctor[M], mab: Arbitrary[M[A, D]], fba: Arbitrary[(B => A)], fcb: Arbitrary[(C => B)], fde: Arbitrary[(D => E)], fef: Arbitrary[(E => F)], e: Equal[M[C, F]]): Prop = 205 forAll(M.profunctorLaw.composite[A, B, C, D, E, F] _ ) 206 207 def laws[M[_,_]](implicit F: Profunctor[M], af: Arbitrary[M[Int, Int]], itf: Arbitrary[(Int => Int)], e: Equal[M[Int, Int]]): Properties = 208 newProperties("profunctor") { p => 209 p.property("identity") = identity[M, Int, Int] 210 p.property("composite") = compose[M, Int, Int, Int, Int, Int, Int] 211 } 212 } 213 214 object strong { 215 def firstIsSwappedSecond[M[_,_], A, B, C](implicit M: Strong[M], mba: Arbitrary[M[A, B]], eq: Equal[M[(A,C),(B,C)]]): Prop = 216 forAll(M.strongLaw.firstIsSwappedSecond[A, B, C] _) 217 218 def secondIsSwappedFirst[M[_,_], A, B, C](implicit M: Strong[M], mba: Arbitrary[M[A, B]], eq: Equal[M[(C,A),(C,B)]]): Prop = 219 forAll(M.strongLaw.secondIsSwappedFirst[A, B, C] _) 220 221 def mapfstEqualsFirstAndThenMapsnd[M[_,_], A, B, C](implicit M: Strong[M], mba: Arbitrary[M[A, B]], eq: Equal[M[(A,C),B]]): Prop = 222 forAll(M.strongLaw.mapfstEqualsFirstAndThenMapsnd[A, B, C] _) 223 224 def mapfstEqualsSecondAndThenMapsnd[M[_,_], A, B, C](implicit M: Strong[M], mba: Arbitrary[M[A, B]], eq: Equal[M[(C,A),B]]): Prop = 225 forAll(M.strongLaw.mapfstEqualsSecondAndThenMapsnd[A, B, C] _) 226 227 def dinaturalityFirst[M[_,_], A, B, C, D](implicit M: Strong[M], mba: Arbitrary[M[A, B]], cd: Arbitrary[C => D], eq: Equal[M[(A,C),(B,D)]]): Prop = 228 forAll(M.strongLaw.dinaturalityFirst[A, B, C, D] _) 229 230 def dinaturalitySecond[M[_,_], A, B, C, D](implicit M: Strong[M], mba: Arbitrary[M[A, B]], cd: Arbitrary[C => D], eq: Equal[M[(C,A), (D,B)]]): Prop = 231 forAll(M.strongLaw.dinaturalitySecond[A, B, C, D] _) 232 233 def firstFirstIsDimap[M[_,_], A, B, C, D](implicit M: Strong[M], mba: Arbitrary[M[A, B]], eq: Equal[M[((A,C),D),((B,C),D)]]): Prop = 234 forAll(M.strongLaw.firstFirstIsDimap[A, B, C, D] _) 235 236 def secondSecondIsDimap[M[_,_], A, B, C, D](implicit M: Strong[M], mba: Arbitrary[M[A, B]], eq: Equal[M[(D,(C,A)),(D,(C,B))]]): Prop = 237 forAll(M.strongLaw.secondSecondIsDimap[A, B, C, D] _) 238 239 def laws[M[_,_]](implicit 240 F: Strong[M], 241 af: Arbitrary[M[Int, Int]], 242 eq0: Equal[M[Int,Int]], 243 eq1: Equal[M[(Int,Int), (Int,Int)]], 244 eq2: Equal[M[(Int,Int), Int]], 245 eq3: Equal[M[((Int,Int),Int),((Int,Int),Int)]], 246 eq4: Equal[M[(Int,(Int,Int)),(Int,(Int,Int))]]): Properties = 247 newProperties("strong") { p => 248 p.include(ScalazProperties.profunctor.laws[M]) 249 p.property("firstIsSwappedSecond") = firstIsSwappedSecond[M, Int, Int, Int] 250 p.property("secondIsSwappedFirst") = secondIsSwappedFirst[M, Int, Int, Int] 251 p.property("mapfstEqualsFirstAndThenMapsnd") = mapfstEqualsFirstAndThenMapsnd[M, Int, Int, Int] 252 p.property("dinaturalityFirst") = dinaturalityFirst[M, Int, Int, Int, Int] 253 p.property("dinaturalitySecond") = dinaturalitySecond[M, Int, Int, Int, Int] 254 p.property("firstFirstIsDimap") = firstFirstIsDimap[M, Int, Int, Int, Int] 255 p.property("secondSecondIsDimap") = secondSecondIsDimap[M, Int, Int, Int, Int] 256 } 257 } 258 259 object align { 260 def collapse[F[_], A](implicit F: Align[F], E: Equal[F[A \&/ A]], A: Arbitrary[F[A]]): Prop = 261 forAll(F.alignLaw.collapse[A] _) 262 def laws[F[_]](implicit F: Align[F], af: Arbitrary[F[Int]], 263 e: Equal[F[Int]], ef: Equal[F[Int \&/ Int]]): Properties = 264 newProperties("align") { p => 265 p.include(functor.laws[F]) 266 p.property("collapse") = collapse[F, Int] 267 } 268 } 269 270 object apply {self => 271 def composition[F[_], X, Y, Z](implicit ap: Apply[F], afx: Arbitrary[F[X]], au: Arbitrary[F[Y => Z]], 272 av: Arbitrary[F[X => Y]], e: Equal[F[Z]]): Prop = forAll(ap.applyLaw.composition[X, Y, Z] _) 273 274 def laws[F[_]](implicit F: Apply[F], af: Arbitrary[F[Int]], 275 aff: Arbitrary[F[Int => Int]], e: Equal[F[Int]]): Properties = 276 newProperties("apply") { p => 277 implicit val r: Reducer[F[Int], F[Int]] = F.liftReducer(Reducer.identityReducer[Int]) 278 279 p.include(functor.laws[F]) 280 p.include(reducer.laws[F[Int], F[Int]]) 281 p.property("composition") = self.composition[F, Int, Int, Int] 282 } 283 } 284 285 object applicative { 286 def identity[F[_], X](implicit f: Applicative[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 287 forAll(f.applicativeLaw.identityAp[X] _) 288 289 def homomorphism[F[_], X, Y](implicit ap: Applicative[F], ax: Arbitrary[X], af: Arbitrary[X => Y], e: Equal[F[Y]]): Prop = 290 forAll(ap.applicativeLaw.homomorphism[X, Y] _) 291 292 def interchange[F[_], X, Y](implicit ap: Applicative[F], ax: Arbitrary[X], afx: Arbitrary[F[X => Y]], e: Equal[F[Y]]): Prop = 293 forAll(ap.applicativeLaw.interchange[X, Y] _) 294 295 def mapApConsistency[F[_], X, Y](implicit ap: Applicative[F], ax: Arbitrary[F[X]], afx: Arbitrary[X => Y], e: Equal[F[Y]]): Prop = 296 forAll(ap.applicativeLaw.mapLikeDerived[X, Y] _) 297 298 def laws[F[_]](implicit F: Applicative[F], af: Arbitrary[F[Int]], 299 aff: Arbitrary[F[Int => Int]], e: Equal[F[Int]]): Properties = 300 newProperties("applicative") { p => 301 p.include(ScalazProperties.apply.laws[F]) 302 p.property("identity") = applicative.identity[F, Int] 303 p.property("homomorphism") = applicative.homomorphism[F, Int, Int] 304 p.property("interchange") = applicative.interchange[F, Int, Int] 305 p.property("map consistent with ap") = applicative.mapApConsistency[F, Int, Int] 306 } 307 } 308 309 object applicativeError{ 310 def raisedErrorsHandled[F[_], E, A](implicit A: ApplicativeError[F, E], eq: Equal[F[A]], ae: Arbitrary[E], afea: Arbitrary[E => F[A]]): Prop = 311 forAll(A.applicativeErrorLaws.raisedErrorsHandled[A] _) 312 313 def laws[F[_], E](implicit A: ApplicativeError[F, E], am: Arbitrary[F[Int]], afap: Arbitrary[F[Int => Int]], aeq: Equal[F[Int]], ae: Arbitrary[E], afea: Arbitrary[E => F[Int]]): Properties = 314 newProperties("applicative error"){ p => 315 p.include(applicative.laws[F]) 316 p.property("raisedErrorsHandled") = raisedErrorsHandled[F, E, Int] 317 } 318 } 319 320 object alt { 321 def laws[F[_]](implicit F: Applicative[F], af: Arbitrary[F[Int]], 322 aff: Arbitrary[F[Int => Int]], e: Equal[F[Int]]): Properties = 323 newProperties("alt") { p => 324 p.include(applicative.laws[F]) 325 } 326 } 327 328 object bind { 329 def associativity[M[_], X, Y, Z](implicit M: Bind[M], amx: Arbitrary[M[X]], af: Arbitrary[(X => M[Y])], 330 ag: Arbitrary[(Y => M[Z])], emz: Equal[M[Z]]): Prop = 331 forAll(M.bindLaw.associativeBind[X, Y, Z] _) 332 333 def bindApConsistency[M[_], X, Y](implicit M: Bind[M], amx: Arbitrary[M[X]], 334 af: Arbitrary[M[X => Y]], emy: Equal[M[Y]]): Prop = 335 forAll(M.bindLaw.apLikeDerived[X, Y] _) 336 337 def laws[M[_]](implicit a: Bind[M], am: Arbitrary[M[Int]], 338 af: Arbitrary[Int => M[Int]], ag: Arbitrary[M[Int => Int]], e: Equal[M[Int]]): Properties = 339 newProperties("bind") { p => 340 p.include(ScalazProperties.apply.laws[M]) 341 342 p.property("associativity") = bind.associativity[M, Int, Int, Int] 343 p.property("ap consistent with bind") = bind.bindApConsistency[M, Int, Int] 344 } 345 } 346 347 object bindRec { 348 def tailrecBindConsistency[M[_], X](implicit M: BindRec[M], ax: Arbitrary[X], af: Arbitrary[X => M[X]], 349 emx: Equal[M[X]]): Prop = 350 forAll(M.bindRecLaw.tailrecBindConsistency[X] _) 351 352 def laws[M[_]](implicit a: BindRec[M], am: Arbitrary[M[Int]], 353 af: Arbitrary[Int => M[Int]], ag: Arbitrary[M[Int => Int]], e: Equal[M[Int]]): Properties = 354 newProperties("bindRec") { p => 355 p.include(bind.laws[M]) 356 p.property("tailrecM is consistent with bind") = bindRec.tailrecBindConsistency[M, Int] 357 } 358 } 359 360 object monad { 361 def rightIdentity[M[_], X](implicit M: Monad[M], e: Equal[M[X]], a: Arbitrary[M[X]]): Prop = 362 forAll(M.monadLaw.rightIdentity[X] _) 363 364 def leftIdentity[M[_], X, Y](implicit am: Monad[M], emy: Equal[M[Y]], ax: Arbitrary[X], af: Arbitrary[(X => M[Y])]): Prop = 365 forAll(am.monadLaw.leftIdentity[X, Y] _) 366 367 def laws[M[_]](implicit a: Monad[M], am: Arbitrary[M[Int]], 368 af: Arbitrary[Int => M[Int]], ag: Arbitrary[M[Int => Int]], e: Equal[M[Int]]): Properties = 369 newProperties("monad") { p => 370 p.include(applicative.laws[M]) 371 p.include(bind.laws[M]) 372 p.property("right identity") = monad.rightIdentity[M, Int] 373 p.property("left identity") = monad.leftIdentity[M, Int, Int] 374 } 375 } 376 377 object cobind { 378 def cobindAssociative[F[_], A, B, C, D](implicit F: Cobind[F], D: Equal[D], fa: Arbitrary[F[A]], 379 f: Arbitrary[F[A] => B], g: Arbitrary[F[B] => C], h: Arbitrary[F[C] => D]): Prop = 380 forAll(F.cobindLaw.cobindAssociative[A, B, C, D] _) 381 382 def laws[F[_]](implicit a: Cobind[F], f: Arbitrary[F[Int] => Int], am: Arbitrary[F[Int]], e: Equal[F[Int]]): Properties = 383 newProperties("cobind") { p => 384 p.include(functor.laws[F]) 385 p.property("cobind associative") = cobindAssociative[F, Int, Int, Int, Int] 386 } 387 } 388 389 object comonad { 390 def cobindLeftIdentity[F[_], A](implicit F: Comonad[F], F0: Equal[F[A]], fa: Arbitrary[F[A]]): Prop = 391 forAll(F.comonadLaw.cobindLeftIdentity[A] _) 392 393 def cobindRightIdentity[F[_], A, B](implicit F: Comonad[F], F0: Equal[B], fa: Arbitrary[F[A]], f: Arbitrary[F[A] => B]): Prop = 394 forAll(F.comonadLaw.cobindRightIdentity[A, B] _) 395 396 def laws[F[_]](implicit a: Comonad[F], am: Arbitrary[F[Int]], 397 af: Arbitrary[F[Int] => Int], e: Equal[F[Int]]): Properties = 398 newProperties("comonad") { p => 399 p.include(cobind.laws[F]) 400 p.property("cobind left identity") = cobindLeftIdentity[F, Int] 401 p.property("cobind right identity") = cobindRightIdentity[F, Int, Int] 402 } 403 } 404 405 object density { 406 def densityIsLeftKan[F[_], A, B](implicit F: Density[F, A], F0: Equal[B], fa: Arbitrary[F[A]], fab: Arbitrary[F[A] => B]): Prop = 407 forAll(F.densityLaw.densityIsLeftKan[A,B] _) 408 409 def leftKanIsDensity[F[_], A, B](implicit F: Density[F, A], F0: Equal[F[A]], fa: Arbitrary[F[A]], fab: Arbitrary[F[A] => B]): Prop = 410 forAll(F.densityLaw.leftKanIsDensity[A,B] _) 411 412 def laws[F[_]](implicit a: Density[F, Int], am: Arbitrary[F[Int]], 413 af: Arbitrary[F[Int] => Int], e: Equal[F[Int]]): Properties = 414 newProperties("density") { p => 415 p.property("density is left kan") = densityIsLeftKan[F, Int, Int] 416 p.property("left kan is density") = leftKanIsDensity[F, Int, Int] 417 } 418 } 419 420 private def resizeProp(p: Prop, max: Int): Prop = new PropFromFun( 421 params => p(params.withSize(params.size % (max + 1))) 422 ) 423 424 object traverse { 425 def identityTraverse[F[_], X, Y](implicit f: Traverse[F], afx: Arbitrary[F[X]], axy: Arbitrary[X => Y], ef: Equal[F[Y]]): Prop = 426 forAll(f.traverseLaw.identityTraverse[X, Y] _) 427 428 def purity[F[_], G[_], X](implicit f: Traverse[F], afx: Arbitrary[F[X]], G: Applicative[G], ef: Equal[G[F[X]]]): Prop = 429 forAll(f.traverseLaw.purity[G, X] _) 430 431 def sequentialFusion[F[_], N[_], M[_], A, B, C](implicit fa: Arbitrary[F[A]], amb: Arbitrary[A => M[B]], bnc: Arbitrary[B => N[C]], 432 F: Traverse[F], N: Applicative[N], M: Applicative[M], MN: Equal[M[N[F[C]]]]): Prop = 433 forAll(F.traverseLaw.sequentialFusion[N, M, A, B, C] _) 434 435 def naturality[F[_], N[_], M[_], A](nat: (M ~> N)) 436 (implicit fma: Arbitrary[F[M[A]]], F: Traverse[F], N: Applicative[N], M: Applicative[M], NFA: Equal[N[F[A]]]): Prop = 437 forAll(F.traverseLaw.naturality[N, M, A](nat) _) 438 439 def parallelFusion[F[_], N[_], M[_], A, B](implicit fa: Arbitrary[F[A]], amb: Arbitrary[A => M[B]], anb: Arbitrary[A => N[B]], 440 F: Traverse[F], N: Applicative[N], M: Applicative[M], MN: Equal[(M[F[B]], N[F[B]])]): Prop = 441 forAll(F.traverseLaw.parallelFusion[N, M, A, B] _) 442 443 def laws[F[_]](implicit fa: Arbitrary[F[Int]], F: Traverse[F], EF: Equal[F[Int]]): Properties = 444 newProperties("traverse") { p => 445 p.include(functor.laws[F]) 446 p.include(foldable.laws[F]) 447 p.property("identity traverse") = identityTraverse[F, Int, Int] 448 449 import std.list._, std.option._, std.stream._ 450 451 p.property("purity.option") = purity[F, Option, Int] 452 p.property("purity.stream") = purity[F, Stream, Int] 453 454 p.property("sequential fusion") = resizeProp(sequentialFusion[F, Option, List, Int, Int, Int], 3) 455 // TODO naturality, parallelFusion 456 } 457 } 458 459 object bifoldable { 460 def leftFMConsistent[F[_, _], A, B](implicit F: Bifoldable[F], afa: Arbitrary[F[A, B]], ea: Equal[A], eb: Equal[B]): Prop = 461 forAll(F.bifoldableLaw.leftFMConsistent[A, B] _) 462 463 def rightFMConsistent[F[_, _], A, B](implicit F: Bifoldable[F], afa: Arbitrary[F[A, B]], ea: Equal[A], eb: Equal[B]): Prop = 464 forAll(F.bifoldableLaw.rightFMConsistent[A, B] _) 465 466 def laws[F[_, _]](implicit fa: Arbitrary[F[Int, Int]], F: Bifoldable[F]): Properties = 467 newProperties("bifoldable") { p => 468 p.property("consistent left bifold") = leftFMConsistent[F, Int, Int] 469 p.property("consistent right bifold") = rightFMConsistent[F, Int, Int] 470 implicit val left = F.leftFoldable[Int] 471 implicit val right = F.rightFoldable[Int] 472 p.include(foldable.laws[F[*, Int]]) 473 p.include(foldable.laws[F[Int, *]]) 474 } 475 } 476 477 object bitraverse { 478 def laws[F[_, _]](implicit fa: Arbitrary[F[Int,Int]], F: Bitraverse[F], EF: Equal[F[Int, Int]]): Properties = 479 newProperties("bitraverse") { p => 480 p.include(bifoldable.laws[F]) 481 implicit val left = F.leftTraverse[Int] 482 implicit val right = F.rightTraverse[Int] 483 p.include(traverse.laws[F[*, Int]]) 484 p.include(traverse.laws[F[Int, *]]) 485 } 486 } 487 488 object plus { 489 def associative[F[_], X](implicit f: Plus[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 490 forAll(f.plusLaw.associative[X] _) 491 492 def laws[F[_]](implicit F: Plus[F], afx: Arbitrary[F[Int]], ef: Equal[F[Int]]): Properties = 493 newProperties("plus") { p => 494 p.include(semigroup.laws[F[Int]](F.semigroup[Int], implicitly, implicitly)) 495 p.property("associative") = associative[F, Int] 496 } 497 } 498 499 object plusEmpty { 500 def leftPlusIdentity[F[_], X](implicit f: PlusEmpty[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 501 forAll(f.plusEmptyLaw.leftPlusIdentity[X] _) 502 503 def rightPlusIdentity[F[_], X](implicit f: PlusEmpty[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 504 forAll(f.plusEmptyLaw.rightPlusIdentity[X] _) 505 506 def laws[F[_]](implicit F: PlusEmpty[F], afx: Arbitrary[F[Int]], ef: Equal[F[Int]]): Properties = 507 newProperties("plusEmpty") { p => 508 p.include(plus.laws[F]) 509 p.include(monoid.laws[F[Int]](F.monoid[Int], implicitly, implicitly)) 510 p.property("left plus identity") = leftPlusIdentity[F, Int] 511 p.property("right plus identity") = rightPlusIdentity[F, Int] 512 } 513 } 514 515 object isEmpty { 516 def emptyIsEmpty[F[_], X](implicit f: IsEmpty[F]):Prop = 517 f.isEmptyLaw.emptyIsEmpty[X] 518 519 def emptyPlusIdentity[F[_], X](implicit f: IsEmpty[F], afx: Arbitrary[F[X]]): Prop = 520 forAll(f.isEmptyLaw.emptyPlusIdentity[X] _) 521 522 def laws[F[_]](implicit F: IsEmpty[F], afx: Arbitrary[F[Int]], ef: Equal[F[Int]]): Properties = 523 newProperties("isEmpty") { p => 524 p.include(plusEmpty.laws[F]) 525 p.property("empty is empty") = emptyIsEmpty[F, Int] 526 p.property("empty plus identity") = emptyPlusIdentity[F, Int] 527 } 528 } 529 530 object monadPlus { 531 def emptyMap[F[_], X](implicit f: MonadPlus[F], afx: Arbitrary[X => X], ef: Equal[F[X]]): Prop = 532 forAll(f.monadPlusLaw.emptyMap[X] _) 533 534 def leftZero[F[_], X](implicit F: MonadPlus[F], afx: Arbitrary[X => F[X]], ef: Equal[F[X]]): Prop = 535 forAll(F.monadPlusLaw.leftZero[X] _) 536 537 def rightZero[F[_], X](implicit F: MonadPlus[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 538 forAll(F.strongMonadPlusLaw.rightZero[X] _) 539 540 def laws[F[_]](implicit F: MonadPlus[F], afx: Arbitrary[F[Int]], afy: Arbitrary[F[Int => Int]], ef: Equal[F[Int]]): Properties = 541 newProperties("monad plus") { p => 542 p.include(monad.laws[F]) 543 p.include(plusEmpty.laws[F]) 544 p.property("empty map") = emptyMap[F, Int] 545 p.property("left zero") = leftZero[F, Int] 546 } 547 def strongLaws[F[_]](implicit F: MonadPlus[F], afx: Arbitrary[F[Int]], afy: Arbitrary[F[Int => Int]], ef: Equal[F[Int]]): Properties = 548 newProperties("monad plus") { p => 549 p.include(laws[F]) 550 p.property("right zero") = rightZero[F, Int] 551 } 552 } 553 554 object foldable { 555 def leftFMConsistent[F[_], A](implicit F: Foldable[F], afa: Arbitrary[F[A]], ea: Equal[A]): Prop = 556 forAll(F.foldableLaw.leftFMConsistent[A] _) 557 558 def rightFMConsistent[F[_], A](implicit F: Foldable[F], afa: Arbitrary[F[A]], ea: Equal[A]): Prop = 559 forAll(F.foldableLaw.rightFMConsistent[A] _) 560 561 def laws[F[_]](implicit fa: Arbitrary[F[Int]], F: Foldable[F]): Properties = 562 newProperties("foldable") { p => 563 p.property("consistent left fold") = leftFMConsistent[F, Int] 564 p.property("consistent right fold") = rightFMConsistent[F, Int] 565 } 566 } 567 568 object foldable1 { 569 def leftFM1Consistent[F[_], A](implicit F: Foldable1[F], fa: Arbitrary[F[A]], ea: Equal[A]): Prop = 570 forAll(F.foldable1Law.leftFM1Consistent[A] _) 571 572 def rightFM1Consistent[F[_], A](implicit F: Foldable1[F], fa: Arbitrary[F[A]], ea: Equal[A]): Prop = 573 forAll(F.foldable1Law.rightFM1Consistent[A] _) 574 575 def laws[F[_]](implicit fa: Arbitrary[F[Int]], 576 F: Foldable1[F]): Properties = 577 newProperties("foldable1") { p => 578 p.include(foldable.laws[F]) 579 p.property("consistent left fold1") = leftFM1Consistent[F, Int] 580 p.property("consistent right fold1") = rightFM1Consistent[F, Int] 581 } 582 } 583 584 object traverse1 { 585 def identityTraverse1[F[_], X, Y](implicit f: Traverse1[F], afx: Arbitrary[F[X]], axy: Arbitrary[X => Y], ef: Equal[F[Y]]): Prop = 586 forAll(f.traverse1Law.identityTraverse1[X, Y] _) 587 588 def sequentialFusion1[F[_], N[_], M[_], A, B, C](implicit fa: Arbitrary[F[A]], amb: Arbitrary[A => M[B]], bnc: Arbitrary[B => N[C]], 589 F: Traverse1[F], N: Apply[N], M: Apply[M], MN: Equal[M[N[F[C]]]]): Prop = 590 forAll(F.traverse1Law.sequentialFusion1[N, M, A, B, C] _) 591 592 def naturality1[F[_], N[_], M[_], A](nat: (M ~> N)) 593 (implicit fma: Arbitrary[F[M[A]]], F: Traverse1[F], N: Apply[N], M: Apply[M], NFA: Equal[N[F[A]]]): Prop = 594 forAll(F.traverse1Law.naturality1[N, M, A](nat) _) 595 596 def parallelFusion1[F[_], N[_], M[_], A, B](implicit fa: Arbitrary[F[A]], amb: Arbitrary[A => M[B]], anb: Arbitrary[A => N[B]], 597 F: Traverse1[F], N: Apply[N], M: Apply[M], MN: Equal[(M[F[B]], N[F[B]])]): Prop = 598 forAll(F.traverse1Law.parallelFusion1[N, M, A, B] _) 599 600 def laws[F[_]](implicit fa: Arbitrary[F[Int]], F: Traverse1[F], EF: Equal[F[Int]]): Properties = 601 newProperties("traverse1") { p => 602 p.include(traverse.laws[F]) 603 p.include(foldable1.laws[F]) 604 p.property("identity traverse1") = identityTraverse1[F, Int, Int] 605 606 import std.list._, std.option._ 607 608 p.property("sequential fusion (1)") = resizeProp(sequentialFusion1[F, Option, List, Int, Int, Int], 3) 609 // TODO naturality1, parallelFusion1 610 } 611 } 612 613 object zip { 614 def zipPreservation[F[_], X](implicit F: Zip[F], FF: Functor[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 615 forAll(F.zipLaw.zipPreservation[X] _) 616 617 def zipSymmetric[F[_], X, Y](implicit F: Zip[F], FF: Functor[F], afx: Arbitrary[F[X]], afy: Arbitrary[F[Y]], ef: Equal[F[X]]): Prop = 618 forAll(F.zipLaw.zipSymmetric[X, Y] _) 619 620 def laws[F[_]](implicit fa: Arbitrary[F[Int]], F: Zip[F], FF: Functor[F], EF: Equal[F[Int]]): Properties = 621 newProperties("zip") { p => 622 p.property("preserves structure") = zipPreservation[F, Int] 623 p.property("symmetry") = zipSymmetric[F, Int, Int] 624 } 625 } 626 627 object contravariant { 628 def identity[F[_], X](implicit F: Contravariant[F], afx: Arbitrary[F[X]], ef: Equal[F[X]]): Prop = 629 forAll(F.contravariantLaw.identity[X] _) 630 631 def composite[F[_], X, Y, Z](implicit F: Contravariant[F], af: Arbitrary[F[Z]], axy: Arbitrary[(X => Y)], 632 ayz: Arbitrary[(Y => Z)], ef: Equal[F[X]]): Prop = 633 forAll(F.contravariantLaw.composite[Z, Y, X] _) 634 635 def laws[F[_]](implicit F: Contravariant[F], af: Arbitrary[F[Int]], axy: Arbitrary[(Int => Int)], 636 ef: Equal[F[Int]]): Properties = 637 newProperties("contravariant") { p => 638 p.include(invariantFunctor.laws[F]) 639 p.property("identity") = identity[F, Int] 640 p.property("composite") = composite[F, Int, Int, Int] 641 } 642 } 643 644 object divide { 645 def composition[F[_], A](implicit F: Divide[F], A: Arbitrary[F[A]], E: Equal[F[A]]): Prop = 646 forAll(F.divideLaw.composition[A] _) 647 648 def laws[F[_]](implicit F: Divide[F], af: Arbitrary[F[Int]], axy: Arbitrary[Int => Int], 649 ef: Equal[F[Int]]): Properties = 650 newProperties("divide") { p => 651 p.include(contravariant.laws[F]) 652 p.property("composition") = composition[F, Int] 653 } 654 } 655 656 object divisible { 657 def rightIdentity[F[_], A](implicit F: Divisible[F], A: Arbitrary[F[A]], E: Equal[F[A]]): Prop = 658 forAll(F.divisibleLaw.rightIdentity[A] _) 659 660 def leftIdentity[F[_], A](implicit F: Divisible[F], A: Arbitrary[F[A]], E: Equal[F[A]]): Prop = 661 forAll(F.divisibleLaw.leftIdentity[A] _) 662 663 def laws[F[_]](implicit F: Divisible[F], af: Arbitrary[F[Int]], axy: Arbitrary[Int => Int], 664 ef: Equal[F[Int]]): Properties = 665 newProperties("divisible") { p => 666 p.include(divide.laws[F]) 667 p.property("right identity") = rightIdentity[F, Int] 668 p.property("left identity") = leftIdentity[F, Int] 669 } 670 } 671 672 object decidable { 673 def laws[F[_]](implicit 674 F: Decidable[F], 675 af: Arbitrary[F[Int]], 676 axy: Arbitrary[Int => Int], 677 ef: Equal[F[Int]]): Properties = 678 newProperties("decidable") { p => 679 p.include(divisible.laws[F]) 680 } 681 } 682 683 object compose { 684 def associative[=>:[_, _], A, B, C, D](implicit ab: Arbitrary[A =>: B], bc: Arbitrary[B =>: C], 685 cd: Arbitrary[C =>: D], C: Compose[=>:], E: Equal[A =>: D]): Prop = 686 forAll(C.composeLaw.associative[A, B, C, D] _) 687 688 def laws[=>:[_, _]](implicit C: Compose[=>:], AB: Arbitrary[Int =>: Int], E: Equal[Int =>: Int]): Properties = 689 newProperties("compose") { p => 690 p.property("associative") = associative[=>:, Int, Int, Int, Int] 691 p.include(semigroup.laws[Int =>: Int](C.semigroup[Int], implicitly, implicitly)) 692 } 693 } 694 695 object category { 696 def leftIdentity[=>:[_, _], A, B](implicit ab: Arbitrary[A =>: B], C: Category[=>:], E: Equal[A =>: B]): Prop = 697 forAll(C.categoryLaw.leftIdentity[A, B] _) 698 699 def rightIdentity[=>:[_, _], A, B](implicit ab: Arbitrary[A =>: B], C: Category[=>:], E: Equal[A =>: B]): Prop = 700 forAll(C.categoryLaw.rightIdentity[A, B] _) 701 702 def laws[=>:[_, _]](implicit C: Category[=>:], AB: Arbitrary[Int =>: Int], E: Equal[Int =>: Int]): Properties = 703 newProperties("category") { p => 704 p.include(compose.laws[=>:]) 705 p.property("left identity") = leftIdentity[=>:, Int, Int] 706 p.property("right identity") = rightIdentity[=>:, Int, Int] 707 p.include(monoid.laws[Int =>: Int](C.monoid[Int], implicitly, implicitly)) 708 } 709 } 710 711 object associative { 712 def leftRight[=>:[_, _], X, Y, Z](implicit F: Associative[=>:], af: Arbitrary[X =>: (Y =>: Z)], ef: Equal[X =>: (Y =>: Z)]): Prop = 713 forAll(F.associativeLaw.leftRight[X, Y, Z] _) 714 715 def rightLeft[=>:[_, _], X, Y, Z](implicit F: Associative[=>:], af: Arbitrary[(X =>: Y) =>: Z], ef: Equal[(X =>: Y) =>: Z]): Prop = 716 forAll(F.associativeLaw.rightLeft[X, Y, Z] _) 717 718 def laws[=>:[_, _]](implicit F: Associative[=>:], 719 al: Arbitrary[(Int =>: Int) =>: Int], ar: Arbitrary[Int =>: (Int =>: Int)], 720 el: Equal[(Int =>: Int) =>: Int], er: Equal[Int =>: (Int =>: Int)]): Properties = 721 newProperties("associative") { p => 722 p.property("left and then right reassociation is identity") = leftRight[=>:, Int, Int, Int] 723 p.property("right and then left reassociation is identity") = rightLeft[=>:, Int, Int, Int] 724 } 725 } 726 727 object bifunctor { 728 def laws[F[_, _]](implicit F: Bifunctor[F], E: Equal[F[Int, Int]], af: Arbitrary[F[Int, Int]], 729 axy: Arbitrary[(Int => Int)]): Properties = 730 newProperties("bifunctor") { p => 731 p.include(functor.laws[F[*, Int]](F.leftFunctor[Int], implicitly, implicitly, implicitly)) 732 p.include(functor.laws[F[Int, *]](F.rightFunctor[Int], implicitly, implicitly, implicitly)) 733 } 734 } 735 736 object lens { 737 def identity[A, B](l: Lens[A, B])(implicit A: Arbitrary[A], EA: Equal[A]): Prop = forAll(l.lensLaw.identity _) 738 def retention[A, B](l: Lens[A, B])(implicit A: Arbitrary[A], B: Arbitrary[B], EB: Equal[B]): Prop = forAll(l.lensLaw.retention _) 739 def doubleSet[A, B](l: Lens[A, B])(implicit A: Arbitrary[A], B: Arbitrary[B], EB: Equal[A]): Prop = forAll(l.lensLaw.doubleSet _) 740 741 def laws[A, B](l: Lens[A, B])(implicit A: Arbitrary[A], B: Arbitrary[B], EA: Equal[A], EB: Equal[B]): Properties = 742 newProperties("lens") { p => 743 p.property("identity") = identity[A, B](l) 744 p.property("retention") = retention[A, B](l) 745 p.property("doubleSet") = doubleSet[A, B](l) 746 } 747 } 748 749 object monadError { 750 def errorsRaised[F[_], E, A](implicit me: MonadError[F, E], eq: Equal[F[A]], ae: Arbitrary[E], aa: Arbitrary[A]): Prop = 751 forAll(me.monadErrorLaw.errorsRaised[A] _) 752 def errorsStopComputation[F[_], E, A](implicit me: MonadError[F, E], eq: Equal[F[A]], ae: Arbitrary[E], aa: Arbitrary[A]): Prop = 753 forAll(me.monadErrorLaw.errorsStopComputation[A] _) 754 755 def laws[F[_], E](implicit me: MonadError[F, E], am: Arbitrary[F[Int]], afap: Arbitrary[F[Int => Int]], aeq: Equal[F[Int]], ae: Arbitrary[E], afea: Arbitrary[E => F[Int]]): Properties = 756 newProperties("monad error"){ p => 757 p.include(monad.laws[F]) 758 p.include(applicativeError.laws[F, E]) 759 p.property("errorsRaised") = errorsRaised[F, E, Int] 760 p.property("errorsStopComputation") = errorsStopComputation[F, E, Int] 761 } 762 } 763 764 object monadTrans { 765 def identity[F[_[_], _], G[_], A](implicit F: MonadTrans[F], G: Monad[G], A: Arbitrary[A], Eq: Equal[F[G, A]]): Prop = 766 forAll(F.monadTransLaw.identity[G, A] _) 767 def composition[F[_[_], _], G[_], A, B](implicit F: MonadTrans[F], G: Monad[G], GA: Arbitrary[G[A]], AGB: Arbitrary[A => G[B]], Eq: Equal[F[G, B]]): Prop = 768 forAll(F.monadTransLaw.composition[G, A, B] _) 769 770 def laws[F[_[_], _], G[_]](implicit F: MonadTrans[F], G: Monad[G], AGI: Arbitrary[G[Int]], Eq: Equal[F[G, Int]]): Properties = 771 newProperties("monadTrans") { p => 772 p.property("identity") = identity[F, G, Int] 773 p.property("composition") = composition[F, G, Int, Int] 774 } 775 } 776}