/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

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