diff --git a/build.sbt b/build.sbt index e0f4d915ab..17266c1dc0 100644 --- a/build.sbt +++ b/build.sbt @@ -24,6 +24,8 @@ lazy val catsDoctestSettings = Seq( doctestWithDependencies := false ) ++ doctestSettings +lazy val algebraVersion = "0.4.2" + lazy val commonSettings = Seq( scalacOptions ++= commonScalacOptions, resolvers ++= Seq( @@ -33,8 +35,8 @@ lazy val commonSettings = Seq( ), libraryDependencies ++= Seq( "com.github.mpilquist" %%% "simulacrum" % "0.7.0", - "org.spire-math" %%% "algebra" % "0.3.1", - "org.spire-math" %%% "algebra-std" % "0.3.1", + "org.spire-math" %%% "algebra" % algebraVersion, + "org.spire-math" %%% "algebra-std" % algebraVersion, "org.typelevel" %%% "machinist" % "0.4.1", compilerPlugin("org.scalamacros" %% "paradise" % "2.1.0" cross CrossVersion.full), compilerPlugin("org.spire-math" %% "kind-projector" % "0.6.3") @@ -179,7 +181,7 @@ lazy val laws = crossProject.crossType(CrossType.Pure) .settings(catsSettings:_*) .settings(disciplineDependencies:_*) .settings(libraryDependencies ++= Seq( - "org.spire-math" %%% "algebra-laws" % "0.3.1", + "org.spire-math" %%% "algebra-laws" % algebraVersion, "org.typelevel" %%% "catalysts-platform" % "0.0.2")) .jsSettings(commonJsSettings:_*) .jvmSettings(commonJvmSettings:_*) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 8d21fbf1b5..a2181c9b48 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -1,6 +1,7 @@ package cats package data +import algebra.std.tuple.tuple2Eq import cats.functor.Bifunctor final case class WriterT[F[_], L, V](run: F[(L, V)]) { @@ -50,12 +51,11 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) { object WriterT extends WriterTInstances with WriterTFunctions private[data] sealed abstract class WriterTInstances extends WriterTInstances0 { + implicit def writerTIdMonad[L:Monoid]: Monad[WriterT[Id, L, ?]] = writerTMonadWriter[Id, L] - // The Eq[(L, V)] can be derived from an Eq[L] and Eq[V], but we are waiting - // on an algebra release that includes /~https://github.com/non/algebra/pull/82 - implicit def writerTIdEq[L, V](implicit E: Eq[(L, V)]): Eq[WriterT[Id, L, V]] = + implicit def writerTIdEq[L: Eq, V: Eq]: Eq[WriterT[Id, L, V]] = writerTEq[Id, L, V] implicit def writerTBifunctor[F[_]:Functor]: Bifunctor[WriterT[F, ?, ?]] = diff --git a/core/src/main/scala/cats/std/anyval.scala b/core/src/main/scala/cats/std/anyval.scala index 7964aa18e9..0d503eefec 100644 --- a/core/src/main/scala/cats/std/anyval.scala +++ b/core/src/main/scala/cats/std/anyval.scala @@ -14,6 +14,7 @@ trait AnyValInstances with DoubleInstances with BooleanInstances with UnitInstances + with TupleInstances trait IntInstances extends algebra.std.IntInstances { diff --git a/core/src/main/scala/cats/std/tuple.scala b/core/src/main/scala/cats/std/tuple.scala index a690245a81..a9e8edef35 100644 --- a/core/src/main/scala/cats/std/tuple.scala +++ b/core/src/main/scala/cats/std/tuple.scala @@ -1,7 +1,7 @@ package cats package std -trait TupleInstances extends Tuple2Instances +trait TupleInstances extends Tuple2Instances with algebra.std.TupleInstances sealed trait Tuple2Instances { implicit val tuple2Bitraverse: Bitraverse[Tuple2] = diff --git a/docs/src/main/tut/monoid.md b/docs/src/main/tut/monoid.md index 183f5c97d3..b31f6e6662 100644 --- a/docs/src/main/tut/monoid.md +++ b/docs/src/main/tut/monoid.md @@ -60,23 +60,9 @@ l.foldMap(i => i.toString) ``` To use this -with a function that produces a tuple, we can define a `Monoid` for a tuple +with a function that produces a tuple, cats also provides a `Monoid` for a tuple that will be valid for any tuple where the types it contains also have a -`Monoid` available: - -```tut:silent -implicit def tupleMonoid[A : Monoid, B : Monoid]: Monoid[(A, B)] = - new Monoid[(A, B)] { - def combine(x: (A, B), y: (A, B)): (A, B) = { - val (xa, xb) = x - val (ya, yb) = y - (Monoid[A].combine(xa, ya), Monoid[B].combine(xb, yb)) - } - def empty: (A, B) = (Monoid[A].empty, Monoid[B].empty) - } -``` - -Thus. +`Monoid` available, thus. ```tut l.foldMap(i => (i, i.toString)) // do both of the above in one pass, hurrah! @@ -90,4 +76,5 @@ trait](/~https://github.com/non/algebra/blob/master/core/src/main/scala/algebra/Mo which is defined in the [algebra project](/~https://github.com/non/algebra) on which it depends. The [`cats` package object](/~https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/package.scala) defines type aliases to the `Monoid` from algebra, so that you can -`import cats.Monoid`. +`import cats.Monoid`. Also the `Monoid` instance for tuple is also [implemented in algebra](/~https://github.com/non/algebra/blob/v0.4.2/project/Boilerplate.scala#L80-L217), +cats merely provides it through [inheritance](/~https://github.com/typelevel/cats/blob/v0.5.0/core/src/main/scala/cats/std/tuple.scala). diff --git a/js/src/test/scala/cats/tests/FutureTests.scala b/js/src/test/scala/cats/tests/FutureTests.scala index 0af2e907e0..b0dc5172dc 100644 --- a/js/src/test/scala/cats/tests/FutureTests.scala +++ b/js/src/test/scala/cats/tests/FutureTests.scala @@ -4,7 +4,6 @@ package tests import cats.data.Xor import cats.laws.discipline._ -import cats.laws.discipline.eq.tuple3Eq import cats.js.std.Await import cats.js.std.future.futureComonad import cats.tests.CatsSuite diff --git a/jvm/src/test/scala/cats/tests/FutureTests.scala b/jvm/src/test/scala/cats/tests/FutureTests.scala index 58a46e13dd..8fba502584 100644 --- a/jvm/src/test/scala/cats/tests/FutureTests.scala +++ b/jvm/src/test/scala/cats/tests/FutureTests.scala @@ -5,7 +5,6 @@ package tests import cats.data.Xor import cats.laws.discipline._ import cats.laws.discipline.arbitrary.evalArbitrary -import cats.laws.discipline.eq.tuple3Eq import cats.jvm.std.future.futureComonad import cats.tests.CatsSuite diff --git a/laws/src/main/scala/cats/laws/discipline/Eq.scala b/laws/src/main/scala/cats/laws/discipline/Eq.scala index 730822231d..c39879c07b 100644 --- a/laws/src/main/scala/cats/laws/discipline/Eq.scala +++ b/laws/src/main/scala/cats/laws/discipline/Eq.scala @@ -31,18 +31,6 @@ object eq { (a: A) => showInstance.show(a) } - // Temporary, see /~https://github.com/non/algebra/pull/82 - implicit def tuple2Eq[A, B](implicit A: Eq[A], B: Eq[B]): Eq[(A, B)] = - new Eq[(A, B)] { - def eqv(x: (A, B), y: (A, B)): Boolean = - A.eqv(x._1, y._1) && B.eqv(x._2, y._2) - } - - implicit def tuple3Eq[A, B, C](implicit EqA: Eq[A], EqB: Eq[B], EqC: Eq[C]): Eq[(A, B, C)] = - new Eq[(A, B, C)] { - def eqv(x: (A, B, C), y: (A, B, C)): Boolean = EqA.eqv(x._1, y._1) && EqB.eqv(x._2, y._2) && EqC.eqv(x._3, y._3) - } - /** * Create an approximation of Eq[Semigroup[A]] by generating values for A * and comparing the application of the two combine functions. diff --git a/tests/src/test/scala/cats/tests/BitraverseTests.scala b/tests/src/test/scala/cats/tests/BitraverseTests.scala index e981925d80..989c21822a 100644 --- a/tests/src/test/scala/cats/tests/BitraverseTests.scala +++ b/tests/src/test/scala/cats/tests/BitraverseTests.scala @@ -4,7 +4,6 @@ package tests import cats.data.Xor import cats.laws.discipline.{BitraverseTests, SerializableTests} import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq.tuple2Eq class BitraverseTest extends CatsSuite { type XorTuple2[A, B] = Xor[(A, B), (A, B)] diff --git a/tests/src/test/scala/cats/tests/ComposeTests.scala b/tests/src/test/scala/cats/tests/ComposeTests.scala index 88fcbe3718..2cccfa1eff 100644 --- a/tests/src/test/scala/cats/tests/ComposeTests.scala +++ b/tests/src/test/scala/cats/tests/ComposeTests.scala @@ -2,7 +2,7 @@ package cats package tests import cats.data.{ NonEmptyList, NonEmptyVector } -import cats.laws.discipline.{ AlternativeTests, ApplicativeTests, FoldableTests, CartesianTests, MonoidKTests, SemigroupKTests, arbitrary, eq }, arbitrary._, eq._ +import cats.laws.discipline.{ AlternativeTests, ApplicativeTests, FoldableTests, CartesianTests, MonoidKTests, SemigroupKTests, arbitrary }, arbitrary._ class ComposeTests extends CatsSuite { // we have a lot of generated lists of lists in these tests. We have to tell diff --git a/tests/src/test/scala/cats/tests/EitherTests.scala b/tests/src/test/scala/cats/tests/EitherTests.scala index a104d21cbd..f6e8f6d55b 100644 --- a/tests/src/test/scala/cats/tests/EitherTests.scala +++ b/tests/src/test/scala/cats/tests/EitherTests.scala @@ -1,9 +1,8 @@ package cats package tests -import cats.laws.discipline.{BitraverseTests, TraverseTests, MonadTests, SerializableTests, CartesianTests} -import cats.laws.discipline.eq._ import algebra.laws.OrderLaws +import cats.laws.discipline.{BitraverseTests, TraverseTests, MonadTests, SerializableTests, CartesianTests} class EitherTests extends CatsSuite { diff --git a/tests/src/test/scala/cats/tests/EvalTests.scala b/tests/src/test/scala/cats/tests/EvalTests.scala index 46c490898d..d1388f8c99 100644 --- a/tests/src/test/scala/cats/tests/EvalTests.scala +++ b/tests/src/test/scala/cats/tests/EvalTests.scala @@ -5,7 +5,6 @@ import scala.math.min import cats.laws.ComonadLaws import cats.laws.discipline.{CartesianTests, BimonadTests, SerializableTests} import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ import algebra.laws.{GroupLaws, OrderLaws} class EvalTests extends CatsSuite { diff --git a/tests/src/test/scala/cats/tests/FreeApplicativeTests.scala b/tests/src/test/scala/cats/tests/FreeApplicativeTests.scala index c8f6dd8861..4db958c593 100644 --- a/tests/src/test/scala/cats/tests/FreeApplicativeTests.scala +++ b/tests/src/test/scala/cats/tests/FreeApplicativeTests.scala @@ -4,7 +4,6 @@ package tests import cats.arrow.NaturalTransformation import cats.free.FreeApplicative import cats.laws.discipline.{CartesianTests, ApplicativeTests, SerializableTests} -import cats.laws.discipline.eq.{tuple3Eq, tuple2Eq} import cats.data.State import org.scalacheck.{Arbitrary, Gen} diff --git a/tests/src/test/scala/cats/tests/FreeTests.scala b/tests/src/test/scala/cats/tests/FreeTests.scala index 56fe308ac2..c03f86482c 100644 --- a/tests/src/test/scala/cats/tests/FreeTests.scala +++ b/tests/src/test/scala/cats/tests/FreeTests.scala @@ -4,7 +4,6 @@ package tests import cats.arrow.NaturalTransformation import cats.free.{Free, Trampoline} import cats.laws.discipline.{CartesianTests, MonadTests, SerializableTests} -import cats.laws.discipline.eq._ import cats.laws.discipline.arbitrary.function0Arbitrary import org.scalacheck.{Arbitrary, Gen} import Arbitrary.arbFunction1 diff --git a/tests/src/test/scala/cats/tests/IdTests.scala b/tests/src/test/scala/cats/tests/IdTests.scala index d811e9c3ed..115ccc875e 100644 --- a/tests/src/test/scala/cats/tests/IdTests.scala +++ b/tests/src/test/scala/cats/tests/IdTests.scala @@ -2,7 +2,6 @@ package cats package tests import cats.laws.discipline._ -import cats.laws.discipline.eq.tuple3Eq class IdTests extends CatsSuite { implicit val iso = CartesianTests.Isomorphisms.invariant[Id] diff --git a/tests/src/test/scala/cats/tests/IorTests.scala b/tests/src/test/scala/cats/tests/IorTests.scala index 27c7779516..eca8a7c9c9 100644 --- a/tests/src/test/scala/cats/tests/IorTests.scala +++ b/tests/src/test/scala/cats/tests/IorTests.scala @@ -4,7 +4,6 @@ package tests import cats.data.{Xor, Ior} import cats.laws.discipline.{BifunctorTests, TraverseTests, MonadTests, SerializableTests, CartesianTests} import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ import org.scalacheck.Arbitrary._ class IorTests extends CatsSuite { diff --git a/tests/src/test/scala/cats/tests/ListTests.scala b/tests/src/test/scala/cats/tests/ListTests.scala index 98517df453..fc92265ce8 100644 --- a/tests/src/test/scala/cats/tests/ListTests.scala +++ b/tests/src/test/scala/cats/tests/ListTests.scala @@ -4,7 +4,6 @@ package tests import cats.data.NonEmptyList import cats.laws.discipline.{TraverseTests, CoflatMapTests, MonadCombineTests, SerializableTests, CartesianTests} import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ class ListTests extends CatsSuite { diff --git a/tests/src/test/scala/cats/tests/MapTests.scala b/tests/src/test/scala/cats/tests/MapTests.scala index ffa619729a..fb33354c64 100644 --- a/tests/src/test/scala/cats/tests/MapTests.scala +++ b/tests/src/test/scala/cats/tests/MapTests.scala @@ -2,7 +2,6 @@ package cats package tests import cats.laws.discipline.{TraverseTests, FlatMapTests, SerializableTests, CartesianTests} -import cats.laws.discipline.eq._ class MapTests extends CatsSuite { implicit val iso = CartesianTests.Isomorphisms.invariant[Map[Int, ?]] diff --git a/tests/src/test/scala/cats/tests/MonadCombineTests.scala b/tests/src/test/scala/cats/tests/MonadCombineTests.scala index adf8f7df73..32b3577d77 100644 --- a/tests/src/test/scala/cats/tests/MonadCombineTests.scala +++ b/tests/src/test/scala/cats/tests/MonadCombineTests.scala @@ -3,7 +3,6 @@ package tests import cats.data.Xor import cats.laws.discipline.arbitrary.xorArbitrary -import cats.laws.discipline.eq.tuple2Eq class MonadCombineTest extends CatsSuite { test("separate") { diff --git a/tests/src/test/scala/cats/tests/OneAndTests.scala b/tests/src/test/scala/cats/tests/OneAndTests.scala index ad711ea410..84d3cfbbf3 100644 --- a/tests/src/test/scala/cats/tests/OneAndTests.scala +++ b/tests/src/test/scala/cats/tests/OneAndTests.scala @@ -6,7 +6,6 @@ import algebra.laws.{GroupLaws, OrderLaws} import cats.data.{NonEmptyList, OneAnd} import cats.laws.discipline.{ComonadTests, FunctorTests, SemigroupKTests, FoldableTests, MonadTests, SerializableTests, CartesianTests, TraverseTests, ReducibleTests} import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ class OneAndTests extends CatsSuite { // Lots of collections here.. telling ScalaCheck to calm down a bit diff --git a/tests/src/test/scala/cats/tests/OptionTTests.scala b/tests/src/test/scala/cats/tests/OptionTTests.scala index cfe306c921..0873a8cff9 100644 --- a/tests/src/test/scala/cats/tests/OptionTTests.scala +++ b/tests/src/test/scala/cats/tests/OptionTTests.scala @@ -4,7 +4,6 @@ import cats.{Id, Monad, Cartesian, Show} import cats.data.{OptionT, Xor} import cats.laws.discipline.{FunctorTests, SerializableTests, CartesianTests, MonadTests} import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ class OptionTTests extends CatsSuite { diff --git a/tests/src/test/scala/cats/tests/OptionTests.scala b/tests/src/test/scala/cats/tests/OptionTests.scala index 8e9d58c89c..717eca34b1 100644 --- a/tests/src/test/scala/cats/tests/OptionTests.scala +++ b/tests/src/test/scala/cats/tests/OptionTests.scala @@ -3,7 +3,6 @@ package tests import cats.laws.{ApplicativeLaws, CoflatMapLaws, FlatMapLaws, MonadLaws} import cats.laws.discipline.{TraverseTests, CoflatMapTests, MonadCombineTests, SerializableTests, CartesianTests} -import cats.laws.discipline.eq._ class OptionTests extends CatsSuite { checkAll("Option[Int]", CartesianTests[Option].cartesian[Int, Int, Int]) diff --git a/tests/src/test/scala/cats/tests/ProdTests.scala b/tests/src/test/scala/cats/tests/ProdTests.scala index c0c10077f5..0ab63943d6 100644 --- a/tests/src/test/scala/cats/tests/ProdTests.scala +++ b/tests/src/test/scala/cats/tests/ProdTests.scala @@ -4,7 +4,6 @@ package tests import cats.data.Prod import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ class ProdTests extends CatsSuite { implicit val iso = CartesianTests.Isomorphisms.invariant[Prod[Option, List, ?]] diff --git a/tests/src/test/scala/cats/tests/StateTTests.scala b/tests/src/test/scala/cats/tests/StateTTests.scala index 9e0b8a447e..ec61cf725f 100644 --- a/tests/src/test/scala/cats/tests/StateTTests.scala +++ b/tests/src/test/scala/cats/tests/StateTTests.scala @@ -1,6 +1,7 @@ package cats package tests +import algebra.std.tuple.tuple2Eq import cats.laws.discipline.{CartesianTests, MonadStateTests, SerializableTests} import cats.data.{State, StateT} import cats.laws.discipline.eq._ diff --git a/tests/src/test/scala/cats/tests/StreamTests.scala b/tests/src/test/scala/cats/tests/StreamTests.scala index 82df422329..3e9de86445 100644 --- a/tests/src/test/scala/cats/tests/StreamTests.scala +++ b/tests/src/test/scala/cats/tests/StreamTests.scala @@ -2,7 +2,6 @@ package cats package tests import cats.laws.discipline.{CoflatMapTests, MonadCombineTests, SerializableTests, TraverseTests, CartesianTests} -import cats.laws.discipline.eq.tuple3Eq class StreamTests extends CatsSuite { checkAll("Stream[Int]", CartesianTests[Stream].cartesian[Int, Int, Int]) diff --git a/tests/src/test/scala/cats/tests/TupleTests.scala b/tests/src/test/scala/cats/tests/TupleTests.scala index dae6c08429..fdde8f5545 100644 --- a/tests/src/test/scala/cats/tests/TupleTests.scala +++ b/tests/src/test/scala/cats/tests/TupleTests.scala @@ -2,7 +2,6 @@ package cats package tests import cats.laws.discipline.{BitraverseTests, SerializableTests} -import cats.laws.discipline.eq.tuple2Eq class TupleTests extends CatsSuite { checkAll("Tuple2", BitraverseTests[Tuple2].bitraverse[Option, Int, Int, Int, String, String, String]) diff --git a/tests/src/test/scala/cats/tests/ValidatedTests.scala b/tests/src/test/scala/cats/tests/ValidatedTests.scala index e755b1719d..6a3c05b8b2 100644 --- a/tests/src/test/scala/cats/tests/ValidatedTests.scala +++ b/tests/src/test/scala/cats/tests/ValidatedTests.scala @@ -6,7 +6,6 @@ import cats.data.Validated.{Valid, Invalid} import cats.laws.discipline.{BifunctorTests, TraverseTests, ApplicativeErrorTests, SerializableTests, CartesianTests} import org.scalacheck.Arbitrary._ import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq.tuple3Eq import algebra.laws.{OrderLaws, GroupLaws} import scala.util.Try diff --git a/tests/src/test/scala/cats/tests/VectorTests.scala b/tests/src/test/scala/cats/tests/VectorTests.scala index 8444bb1bb0..cb14ee0313 100644 --- a/tests/src/test/scala/cats/tests/VectorTests.scala +++ b/tests/src/test/scala/cats/tests/VectorTests.scala @@ -2,7 +2,6 @@ package cats package tests import cats.laws.discipline.{MonadCombineTests, CoflatMapTests, SerializableTests, TraverseTests, CartesianTests} -import cats.laws.discipline.eq.tuple3Eq class VectorTests extends CatsSuite { checkAll("Vector[Int]", CartesianTests[Vector].cartesian[Int, Int, Int]) diff --git a/tests/src/test/scala/cats/tests/WriterTTests.scala b/tests/src/test/scala/cats/tests/WriterTTests.scala index cd0cc07312..9cfae56628 100644 --- a/tests/src/test/scala/cats/tests/WriterTTests.scala +++ b/tests/src/test/scala/cats/tests/WriterTTests.scala @@ -4,7 +4,6 @@ package tests import cats.data.{Writer, WriterT} import cats.functor.Bifunctor import cats.laws.discipline._ -import cats.laws.discipline.eq._ import cats.laws.discipline.arbitrary._ import algebra.laws.OrderLaws diff --git a/tests/src/test/scala/cats/tests/WriterTests.scala b/tests/src/test/scala/cats/tests/WriterTests.scala index 6b93c1ef72..80cd56aa05 100644 --- a/tests/src/test/scala/cats/tests/WriterTests.scala +++ b/tests/src/test/scala/cats/tests/WriterTests.scala @@ -2,7 +2,6 @@ package cats package tests import cats.data.Writer -import cats.laws.discipline.eq._ class WriterTests extends CatsSuite { test("pure syntax creates a writer with an empty log"){ diff --git a/tests/src/test/scala/cats/tests/XorTTests.scala b/tests/src/test/scala/cats/tests/XorTTests.scala index 7ea4e9b343..d4d2fc4c5b 100644 --- a/tests/src/test/scala/cats/tests/XorTTests.scala +++ b/tests/src/test/scala/cats/tests/XorTTests.scala @@ -1,12 +1,11 @@ package cats package tests +import algebra.laws.OrderLaws import cats.functor.Bifunctor import cats.data.{Xor, XorT} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq.tuple3Eq -import algebra.laws.OrderLaws class XorTTests extends CatsSuite { implicit val eq0 = XorT.xorTEq[List, String, String Xor Int] diff --git a/tests/src/test/scala/cats/tests/XorTests.scala b/tests/src/test/scala/cats/tests/XorTests.scala index 58d0a90de2..f66704ef5f 100644 --- a/tests/src/test/scala/cats/tests/XorTests.scala +++ b/tests/src/test/scala/cats/tests/XorTests.scala @@ -1,12 +1,11 @@ package cats package tests +import algebra.laws.{GroupLaws, OrderLaws} import cats.data.{NonEmptyList, Xor, XorT} import cats.data.Xor._ import cats.laws.discipline.arbitrary._ import cats.laws.discipline.{BitraverseTests, TraverseTests, MonadErrorTests, SerializableTests, CartesianTests} -import cats.laws.discipline.eq.tuple3Eq -import algebra.laws.{GroupLaws, OrderLaws} import org.scalacheck.Arbitrary import org.scalacheck.Arbitrary._