diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala index ba59b02163..1b51488624 100644 --- a/core/src/main/scala/cats/data/EitherT.scala +++ b/core/src/main/scala/cats/data/EitherT.scala @@ -432,7 +432,7 @@ private[data] trait EitherTFunctor[F[_], L] extends Functor[EitherT[F, L, ?]] { private[data] trait EitherTMonad[F[_], L] extends Monad[EitherT[F, L, ?]] with EitherTFunctor[F, L] { implicit val F: Monad[F] - def pure[A](a: A): EitherT[F, L, A] = EitherT(F.pure(Either.right(a))) + def pure[A](a: A): EitherT[F, L, A] = EitherT.pure(a) def flatMap[A, B](fa: EitherT[F, L, A])(f: A => EitherT[F, L, B]): EitherT[F, L, B] = fa flatMap f def tailRecM[A, B](a: A)(f: A => EitherT[F, L, Either[A, B]]): EitherT[F, L, B] = EitherT(F.tailRecM(a)(a0 => F.map(f(a0).value) { @@ -461,11 +461,13 @@ private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, fla.recoverWith(pf) } +/* TODO violates monadFilter right empty law -- re-enable when MonadFilter laws are split in to weak/strong private[data] trait EitherTMonadFilter[F[_], L] extends MonadFilter[EitherT[F, L, ?]] with EitherTMonadError[F, L] { implicit val F: Monad[F] implicit val L: Monoid[L] def empty[A]: EitherT[F, L, A] = EitherT(F.pure(Either.left(L.empty))) } +*/ /* TODO violates right absorbtion, right distributivity, and left distributivity -- re-enable when MonadCombine laws are split in to weak/strong private[data] trait EitherTMonadCombine[F[_], L] extends MonadCombine[EitherT[F, L, ?]] with EitherTMonadFilter[F, L] with EitherTSemigroupK[F, L] { diff --git a/js/src/test/scala/cats/tests/FutureTests.scala b/js/src/test/scala/cats/tests/FutureTests.scala index e248189d34..61f4c1010d 100644 --- a/js/src/test/scala/cats/tests/FutureTests.scala +++ b/js/src/test/scala/cats/tests/FutureTests.scala @@ -2,10 +2,11 @@ package cats package js package tests +import cats.kernel.laws.GroupLaws import cats.laws.discipline._ import cats.js.instances.Await import cats.js.instances.future.futureComonad -import cats.tests.CatsSuite +import cats.tests.{CatsSuite, ListWrapper} import scala.concurrent.Future import scala.concurrent.duration._ @@ -54,4 +55,11 @@ class FutureTests extends CatsSuite { checkAll("Future[Int]", MonadErrorTests[Future, Throwable].monadError[Int, Int, Int]) checkAll("Future[Int]", ComonadTests[Future].comonad[Int, Int, Int]) checkAll("Future", MonadTests[Future].monad[Int, Int, Int]) + + { + implicit val F = ListWrapper.semigroup[Int] + checkAll("Future[ListWrapper[Int]]", GroupLaws[Future[ListWrapper[Int]]].semigroup) + } + + checkAll("Future[Int]", GroupLaws[Future[Int]].monoid) } diff --git a/jvm/src/test/scala/cats/tests/FutureTests.scala b/jvm/src/test/scala/cats/tests/FutureTests.scala index 669d065500..4b72eb8bc1 100644 --- a/jvm/src/test/scala/cats/tests/FutureTests.scala +++ b/jvm/src/test/scala/cats/tests/FutureTests.scala @@ -2,9 +2,10 @@ package cats package jvm package tests +import cats.kernel.laws.GroupLaws import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ -import cats.tests.CatsSuite +import cats.tests.{CatsSuite, ListWrapper} import scala.concurrent.{Await, Future} import scala.concurrent.duration._ @@ -36,4 +37,11 @@ class FutureTests extends CatsSuite { checkAll("Future with Throwable", MonadErrorTests[Future, Throwable].monadError[Int, Int, Int]) checkAll("Future", MonadTests[Future].monad[Int, Int, Int]) + + { + implicit val F = ListWrapper.semigroup[Int] + checkAll("Future[ListWrapper[Int]]", GroupLaws[Future[ListWrapper[Int]]].semigroup) + } + + checkAll("Future[Int]", GroupLaws[Future[Int]].monoid) } diff --git a/tests/src/test/scala/cats/tests/ConstTests.scala b/tests/src/test/scala/cats/tests/ConstTests.scala index 792676ffb2..c79cbeb0a0 100644 --- a/tests/src/test/scala/cats/tests/ConstTests.scala +++ b/tests/src/test/scala/cats/tests/ConstTests.scala @@ -48,6 +48,9 @@ class ConstTests extends CatsSuite { checkAll("Const[?, ?]", BifoldableTests[Const].bifoldable[Int, Int, Int]) checkAll("Bifoldable[Const]", SerializableTests.serializable(Bifoldable[Const])) + checkAll("InvariantMonoidal[Const[String, ?]]", InvariantMonoidalTests[Const[String, ?]].invariantMonoidal[Int, Int, Int]) + checkAll("InvariantMonoidal[Const[String, ?]]", SerializableTests.serializable(InvariantMonoidal[Const[String, ?]])) + test("show") { Const(1).show should === ("Const(1)") diff --git a/tests/src/test/scala/cats/tests/EitherTTests.scala b/tests/src/test/scala/cats/tests/EitherTTests.scala index 73312c9d12..dbe79220ce 100644 --- a/tests/src/test/scala/cats/tests/EitherTTests.scala +++ b/tests/src/test/scala/cats/tests/EitherTTests.scala @@ -243,6 +243,12 @@ class EitherTTests extends CatsSuite { } } + test("flatMap and flatMapF consistent") { + forAll { (eithert: EitherT[List, String, Int], f: Int => EitherT[List, String, Int]) => + eithert.flatMap(f) should === (eithert.flatMapF(f(_).value)) + } + } + test("fold with Id consistent with Either fold") { forAll { (eithert: EitherT[Id, String, Int], f: String => Long, g: Int => Long) => eithert.fold(f, g) should === (eithert.value.fold(f, g)) diff --git a/tests/src/test/scala/cats/tests/NestedTests.scala b/tests/src/test/scala/cats/tests/NestedTests.scala index 0032ea502a..fc108bffe1 100644 --- a/tests/src/test/scala/cats/tests/NestedTests.scala +++ b/tests/src/test/scala/cats/tests/NestedTests.scala @@ -90,6 +90,13 @@ class NestedTests extends CatsSuite { checkAll("Contravariant[Nested[Show, Option, ?]]", SerializableTests.serializable(Contravariant[Nested[Show, Option, ?]])) } + { + // Apply composition + implicit val instance = ListWrapper.applyInstance + checkAll("Nested[List, ListWrapper, ?]", ApplyTests[Nested[List, ListWrapper, ?]].apply[Int, Int, Int]) + checkAll("Apply[Nested[List, ListWrapper, ?]]", SerializableTests.serializable(Apply[Nested[List, ListWrapper, ?]])) + } + { // Applicative composition implicit val instance = ListWrapper.applicative diff --git a/tests/src/test/scala/cats/tests/TryTests.scala b/tests/src/test/scala/cats/tests/TryTests.scala index 3548372aa4..7fe11c3293 100644 --- a/tests/src/test/scala/cats/tests/TryTests.scala +++ b/tests/src/test/scala/cats/tests/TryTests.scala @@ -1,6 +1,7 @@ package cats package tests +import cats.kernel.laws.GroupLaws import cats.laws.{ApplicativeLaws, CoflatMapLaws, FlatMapLaws, MonadLaws} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ @@ -25,6 +26,16 @@ class TryTests extends CatsSuite { checkAll("Try", MonadTests[Try].monad[Int, Int, Int]) checkAll("Monad[Try]", SerializableTests.serializable(Monad[Try])) + { + implicit val F = ListWrapper.semigroup[Int] + + checkAll("Try[ListWrapper[Int]]", GroupLaws[Try[ListWrapper[Int]]].semigroup) + checkAll("Semigroup[Try[ListWrapper[Int]]", SerializableTests.serializable(Semigroup[Try[ListWrapper[Int]]])) + } + + checkAll("Try[Int]", GroupLaws[Try[Int]].monoid) + checkAll("Monoid[Try[Int]]", SerializableTests.serializable(Monoid[Try[Int]])) + test("show") { forAll { fs: Try[String] => fs.show should === (fs.toString) diff --git a/tests/src/test/scala/cats/tests/Tuple2KTests.scala b/tests/src/test/scala/cats/tests/Tuple2KTests.scala index 9b7c993e39..ba0605c9d9 100644 --- a/tests/src/test/scala/cats/tests/Tuple2KTests.scala +++ b/tests/src/test/scala/cats/tests/Tuple2KTests.scala @@ -65,6 +65,13 @@ class Tuple2KTests extends CatsSuite { checkAll("Traverse[Tuple2K[ListWrapper, ListWrapper, ?]]", SerializableTests.serializable(Traverse[Tuple2K[ListWrapper, ListWrapper, ?]])) } + { + implicit val alternative = ListWrapper.alternative + implicit val iso = CartesianTests.Isomorphisms.invariant[Tuple2K[ListWrapper, ListWrapper, ?]] + checkAll("Tuple2K[ListWrapper, ListWrapper, ?]", AlternativeTests[Tuple2K[ListWrapper, ListWrapper, ?]].alternative[Int, Int, Int]) + checkAll("Alternative[Tuple2K[ListWrapper, ListWrapper, ?]]", SerializableTests.serializable(Alternative[Tuple2K[ListWrapper, ListWrapper, ?]])) + } + { implicit val monadCombine = ListWrapper.monadCombine implicit val iso = CartesianTests.Isomorphisms.invariant[Tuple2K[ListWrapper, ListWrapper, ?]]