PageRenderTime 210ms CodeModel.GetById 133ms app.highlight 68ms RepoModel.GetById 1ms app.codeStats 0ms

/scalacheck-binding/src/main/scala/scalaz/scalacheck/ScalazProperties.scala

http://github.com/scalaz/scalaz
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}