diff --git a/core/src/main/scala-2.13+/cats/data/ZipLazyList.scala b/core/src/main/scala-2.13+/cats/data/ZipLazyList.scala index 516054a6253..a00d059dd12 100644 --- a/core/src/main/scala-2.13+/cats/data/ZipLazyList.scala +++ b/core/src/main/scala-2.13+/cats/data/ZipLazyList.scala @@ -45,6 +45,12 @@ object ZipLazyList { def combineK[A](x: ZipLazyList[A], y: ZipLazyList[A]): ZipLazyList[A] = ZipLazyList(cats.instances.lazyList.catsStdInstancesForLazyList.combineK(x.value, y.value)) + + override def prependK[A](a: A, fa: ZipLazyList[A]): ZipLazyList[A] = + ZipLazyList(cats.instances.lazyList.catsStdInstancesForLazyList.prependK(a, fa.value)) + + override def appendK[A](fa: ZipLazyList[A], a: A): ZipLazyList[A] = + ZipLazyList(cats.instances.lazyList.catsStdInstancesForLazyList.appendK(fa.value, a)) } implicit def catsDataEqForZipLazyList[A: Eq]: Eq[ZipLazyList[A]] = diff --git a/core/src/main/scala-2.13+/cats/data/ZipStream.scala b/core/src/main/scala-2.13+/cats/data/ZipStream.scala index 576a75f007d..e0ab28697da 100644 --- a/core/src/main/scala-2.13+/cats/data/ZipStream.scala +++ b/core/src/main/scala-2.13+/cats/data/ZipStream.scala @@ -47,6 +47,12 @@ object ZipStream { def combineK[A](x: ZipStream[A], y: ZipStream[A]): ZipStream[A] = ZipStream(cats.instances.stream.catsStdInstancesForStream.combineK(x.value, y.value)) + + override def prependK[A](a: A, fa: ZipStream[A]): ZipStream[A] = + ZipStream(cats.instances.stream.catsStdInstancesForStream.prependK(a, fa.value)) + + override def appendK[A](fa: ZipStream[A], a: A): ZipStream[A] = + ZipStream(cats.instances.stream.catsStdInstancesForStream.appendK(fa.value, a)) } implicit def catsDataEqForZipStream[A: Eq]: Eq[ZipStream[A]] = diff --git a/core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala b/core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala index 26b684ef540..d3e401d44b4 100644 --- a/core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala +++ b/core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala @@ -668,6 +668,17 @@ sealed abstract private[data] class IRWSTInstances1 extends IRWSTInstances2 { } sealed abstract private[data] class IRWSTInstances2 extends IRWSTInstances3 { + implicit def catsDataNonEmptyAlternativeForIRWST[F[_], E, L, S](implicit + FM: Monad[F], + FA: NonEmptyAlternative[F], + L0: Monoid[L] + ): NonEmptyAlternative[IndexedReaderWriterStateT[F, E, L, S, S, *]] = + new RWSTNonEmptyAlternative[F, E, L, S] { + implicit def G: NonEmptyAlternative[F] = FA + implicit def F: Monad[F] = FM + implicit def L: Monoid[L] = L0 + } + implicit def catsDataAlternativeForIRWST[F[_], E, L, S](implicit FM: Monad[F], FA: Alternative[F], @@ -789,6 +800,10 @@ sealed abstract private[data] class RWSTMonad[F[_], E, L, S] sealed abstract private[data] class IRWSTSemigroupK[F[_], E, L, SA, SB] extends IRWSTSemigroupK1[F, E, L, SA, SB] +sealed abstract private[data] class RWSTNonEmptyAlternative[F[_], E, L, S] + extends IRWSTFunctor[F, E, L, S, S] + with RWSTNonEmptyAlternative1[F, E, L, S] + sealed abstract private[data] class RWSTAlternative[F[_], E, L, S] extends IRWSTFunctor[F, E, L, S, S] with RWSTAlternative1[F, E, L, S] @@ -821,8 +836,54 @@ private trait IRWSTSemigroupK1[F[_], E, L, SA, SB] extends SemigroupK[IndexedRea } } -private trait RWSTAlternative1[F[_], E, L, S] +private trait RWSTNonEmptyAlternative1[F[_], E, L, S] extends IRWSTSemigroupK1[F, E, L, S, S] + with NonEmptyAlternative[ReaderWriterStateT[F, E, L, S, *]] { + + implicit def F: Monad[F] + def G: NonEmptyAlternative[F] + implicit def L: Monoid[L] + + // Enforces binary compatibility for RWSTAlternative1 between 2.6.1 and newer versions. + final protected def pure0[A](a: A): ReaderWriterStateT[F, E, L, S, A] = + ReaderWriterStateT.pure[F, E, L, S, A](a) + + // Enforces binary compatibility for RWSTAlternative1 between 2.6.1 and newer versions. + final protected def ap0[A, B]( + ff: ReaderWriterStateT[F, E, L, S, A => B] + )( + fa: ReaderWriterStateT[F, E, L, S, A] + ): ReaderWriterStateT[F, E, L, S, B] = + ff.flatMap(f => fa.map(f)(F))(F, L) + + def pure[A](a: A): ReaderWriterStateT[F, E, L, S, A] = pure0(a) + + def ap[A, B]( + ff: ReaderWriterStateT[F, E, L, S, A => B] + )( + fa: ReaderWriterStateT[F, E, L, S, A] + ): ReaderWriterStateT[F, E, L, S, B] = + ap0(ff)(fa) + + override def prependK[A]( + a: A, + fa: IndexedReaderWriterStateT[F, E, L, S, S, A] + ): IndexedReaderWriterStateT[F, E, L, S, S, A] = + IndexedReaderWriterStateT { (e, s) => + G.prependK((L.empty, s, a), fa.run(e, s)) + } + + override def appendK[A]( + fa: IndexedReaderWriterStateT[F, E, L, S, S, A], + a: A + ): IndexedReaderWriterStateT[F, E, L, S, S, A] = + IndexedReaderWriterStateT { (e, s) => + G.appendK(fa.run(e, s), (L.empty, s, a)) + } +} + +private trait RWSTAlternative1[F[_], E, L, S] + extends RWSTNonEmptyAlternative1[F, E, L, S] with Alternative[ReaderWriterStateT[F, E, L, S, *]] { implicit def F: Monad[F] @@ -831,11 +892,15 @@ private trait RWSTAlternative1[F[_], E, L, S] def empty[A]: ReaderWriterStateT[F, E, L, S, A] = ReaderWriterStateT.liftF(G.empty[A]) - def pure[A](a: A): ReaderWriterStateT[F, E, L, S, A] = ReaderWriterStateT.pure[F, E, L, S, A](a) + // Must exist in this trait for binary compatibility. + override def pure[A](a: A): ReaderWriterStateT[F, E, L, S, A] = + pure0(a) - def ap[A, B]( + // Must exist in this trait for binary compatibility. + override def ap[A, B]( ff: ReaderWriterStateT[F, E, L, S, A => B] - )(fa: ReaderWriterStateT[F, E, L, S, A]): ReaderWriterStateT[F, E, L, S, B] = - ff.flatMap(f => fa.map(f)(F))(F, L) - + )( + fa: ReaderWriterStateT[F, E, L, S, A] + ): ReaderWriterStateT[F, E, L, S, B] = + ap0(ff)(fa) } diff --git a/core/src/main/scala/cats/data/IndexedStateT.scala b/core/src/main/scala/cats/data/IndexedStateT.scala index 92ff65a2f58..36e09af965b 100644 --- a/core/src/main/scala/cats/data/IndexedStateT.scala +++ b/core/src/main/scala/cats/data/IndexedStateT.scala @@ -299,19 +299,25 @@ sealed abstract private[data] class IndexedStateTInstances extends IndexedStateT } sealed abstract private[data] class IndexedStateTInstances1 extends IndexedStateTInstances2 { + implicit def catsDataNonEmptyAlternativeForIndexedStateT[F[_], S](implicit + FM: Monad[F], + FA: NonEmptyAlternative[F] + ): NonEmptyAlternative[IndexedStateT[F, S, S, *]] with Monad[IndexedStateT[F, S, S, *]] = + new IndexedStateTNonEmptyAlternative[F, S] { implicit def F = FM; implicit def G = FA } + implicit def catsDataMonadErrorForIndexedStateT[F[_], S, E](implicit F0: MonadError[F, E] ): MonadError[IndexedStateT[F, S, S, *], E] = new IndexedStateTMonadError[F, S, E] { implicit def F = F0 } +} +sealed abstract private[data] class IndexedStateTInstances2 extends IndexedStateTInstances3 { implicit def catsDataSemigroupKForIndexedStateT[F[_], SA, SB](implicit F0: Monad[F], G0: SemigroupK[F] ): SemigroupK[IndexedStateT[F, SA, SB, *]] = new IndexedStateTSemigroupK[F, SA, SB] { implicit def F = F0; implicit def G = G0 } -} -sealed abstract private[data] class IndexedStateTInstances2 extends IndexedStateTInstances3 { implicit def catsDataMonadForIndexedStateT[F[_], S](implicit F0: Monad[F]): Monad[IndexedStateT[F, S, S, *]] = new IndexedStateTMonad[F, S] { implicit def F = F0 } } @@ -507,14 +513,28 @@ sealed abstract private[data] class IndexedStateTContravariantMonoidal[F[_], S] ) } -sealed abstract private[data] class IndexedStateTAlternative[F[_], S] +sealed abstract private[data] class IndexedStateTNonEmptyAlternative[F[_], S] extends IndexedStateTMonad[F, S] - with Alternative[IndexedStateT[F, S, S, *]] { - def G: Alternative[F] + with NonEmptyAlternative[IndexedStateT[F, S, S, *]] { + + def G: NonEmptyAlternative[F] def combineK[A](x: IndexedStateT[F, S, S, A], y: IndexedStateT[F, S, S, A]): IndexedStateT[F, S, S, A] = IndexedStateT[F, S, S, A](s => G.combineK(x.run(s), y.run(s)))(G) + override def prependK[A](a: A, fa: IndexedStateT[F, S, S, A]): IndexedStateT[F, S, S, A] = + IndexedStateT[F, S, S, A](s => G.prependK((s, a), fa.run(s)))(G) + + override def appendK[A](fa: IndexedStateT[F, S, S, A], a: A): IndexedStateT[F, S, S, A] = + IndexedStateT[F, S, S, A](s => G.appendK(fa.run(s), (s, a)))(G) +} + +sealed abstract private[data] class IndexedStateTAlternative[F[_], S] + extends IndexedStateTNonEmptyAlternative[F, S] + with Alternative[IndexedStateT[F, S, S, *]] { + + def G: Alternative[F] + def empty[A]: IndexedStateT[F, S, S, A] = IndexedStateT.liftF[F, S, A](G.empty[A])(G) } diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index 581f60600e1..66adcd236b5 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -452,6 +452,11 @@ sealed abstract private[data] class KleisliInstances2 extends KleisliInstances3 } sealed abstract private[data] class KleisliInstances3 extends KleisliInstances4 { + implicit def catsDataNonEmptyAlternativeForKleisli[F[_], A](implicit + F0: NonEmptyAlternative[F] + ): NonEmptyAlternative[Kleisli[F, A, *]] = + new KleisliNonEmptyAlternative[F, A] { def F: NonEmptyAlternative[F] = F0 } + implicit def catsDataMonoidKForKleisli[F[_], A](implicit F0: MonoidK[F]): MonoidK[Kleisli[F, A, *]] = new KleisliMonoidK[F, A] { def F: MonoidK[F] = F0 } @@ -606,9 +611,22 @@ sealed private[data] trait KleisliMonoidK[F[_], A] extends MonoidK[Kleisli[F, A, override def empty[B]: Kleisli[F, A, B] = Kleisli.liftF(F.empty[B]) } +private[data] trait KleisliNonEmptyAlternative[F[_], A] + extends NonEmptyAlternative[Kleisli[F, A, *]] + with KleisliApplicative[F, A] + with KleisliSemigroupK[F, A] { + implicit def F: NonEmptyAlternative[F] + + override def prependK[B](b: B, fa: Kleisli[F, A, B]): Kleisli[F, A, B] = + Kleisli(a => F.prependK(b, fa.run(a))) + + override def appendK[B](fa: Kleisli[F, A, B], b: B): Kleisli[F, A, B] = + Kleisli(a => F.appendK(fa.run(a), b)) +} + private[data] trait KleisliAlternative[F[_], A] extends Alternative[Kleisli[F, A, *]] - with KleisliApplicative[F, A] + with KleisliNonEmptyAlternative[F, A] with KleisliMonoidK[F, A] { implicit def F: Alternative[F] } diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala index b92399c418a..e00f35061ce 100644 --- a/core/src/main/scala/cats/data/Nested.scala +++ b/core/src/main/scala/cats/data/Nested.scala @@ -170,6 +170,12 @@ sealed abstract private[data] class NestedInstances3 extends NestedInstances4 { } sealed abstract private[data] class NestedInstances4 extends NestedInstances5 { + implicit def catsDataNonEmptyAlternativeForNested[F[_]: NonEmptyAlternative, G[_]: Applicative] + : NonEmptyAlternative[Nested[F, G, *]] = + new NestedNonEmptyAlternative[F, G] { + val FG: NonEmptyAlternative[λ[α => F[G[α]]]] = NonEmptyAlternative[F].compose[G] + } + implicit def catsDataApplicativeErrorForNested[F[_], G[_], E](implicit F: ApplicativeError[F, E], G0: Applicative[G] @@ -322,9 +328,22 @@ private[data] trait NestedMonoidK[F[_], G[_]] extends MonoidK[Nested[F, G, *]] w def empty[A]: Nested[F, G, A] = Nested(FG.empty[A]) } +private[data] trait NestedNonEmptyAlternative[F[_], G[_]] + extends NonEmptyAlternative[Nested[F, G, *]] + with NestedApplicative[F, G] + with NestedSemigroupK[F, G] { + def FG: NonEmptyAlternative[λ[α => F[G[α]]]] + + override def prependK[A](a: A, fa: Nested[F, G, A]): Nested[F, G, A] = + Nested(FG.prependK(a, fa.value)) + + override def appendK[A](fa: Nested[F, G, A], a: A): Nested[F, G, A] = + Nested(FG.appendK(fa.value, a)) +} + private[data] trait NestedAlternative[F[_], G[_]] extends Alternative[Nested[F, G, *]] - with NestedApplicative[F, G] + with NestedNonEmptyAlternative[F, G] with NestedMonoidK[F, G] { def FG: Alternative[λ[α => F[G[α]]]] } diff --git a/core/src/main/scala/cats/data/Tuple2K.scala b/core/src/main/scala/cats/data/Tuple2K.scala index 579e2a0e366..815eb96ec18 100644 --- a/core/src/main/scala/cats/data/Tuple2K.scala +++ b/core/src/main/scala/cats/data/Tuple2K.scala @@ -126,6 +126,7 @@ sealed abstract private[data] class Tuple2KInstances1 extends Tuple2KInstances2 def F: Alternative[F] = FF def G: Alternative[G] = GG } + implicit def catsDataFoldableForTuple2K[F[_], G[_]](implicit FF: Foldable[F], GF: Foldable[G] @@ -175,6 +176,14 @@ sealed abstract private[data] class Tuple2KInstances2 extends Tuple2KInstances3 def F: MonoidK[F] = FF def G: MonoidK[G] = GG } + implicit def catsDataNonEmptyAlternativeForTuple2K[F[_], G[_]](implicit + FF: NonEmptyAlternative[F], + GG: NonEmptyAlternative[G] + ): NonEmptyAlternative[λ[α => Tuple2K[F, G, α]]] = + new Tuple2KNonEmptyAlternative[F, G] { + def F: NonEmptyAlternative[F] = FF + def G: NonEmptyAlternative[G] = GG + } } sealed abstract private[data] class Tuple2KInstances3 extends Tuple2KInstances4 { @@ -352,9 +361,23 @@ sealed private[data] trait Tuple2KMonoidK[F[_], G[_]] Tuple2K(F.empty[A], G.empty[A]) } +sealed private[data] trait Tuple2KNonEmptyAlternative[F[_], G[_]] + extends NonEmptyAlternative[λ[α => Tuple2K[F, G, α]]] + with Tuple2KApplicative[F, G] + with Tuple2KSemigroupK[F, G] { + def F: NonEmptyAlternative[F] + def G: NonEmptyAlternative[G] + + override def prependK[A](a: A, fa: Tuple2K[F, G, A]): Tuple2K[F, G, A] = + Tuple2K(F.prependK(a, fa.first), G.prependK(a, fa.second)) + + override def appendK[A](fa: Tuple2K[F, G, A], a: A): Tuple2K[F, G, A] = + Tuple2K(F.appendK(fa.first, a), G.appendK(fa.second, a)) +} + sealed private[data] trait Tuple2KAlternative[F[_], G[_]] extends Alternative[λ[α => Tuple2K[F, G, α]]] - with Tuple2KApplicative[F, G] + with Tuple2KNonEmptyAlternative[F, G] with Tuple2KMonoidK[F, G] { def F: Alternative[F] def G: Alternative[G] diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 80af484a150..c8bd40f0b83 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -535,6 +535,15 @@ sealed abstract private[data] class WriterTInstances8 extends WriterTInstances9 } sealed abstract private[data] class WriterTInstances9 extends WriterTInstances10 { + implicit def catsDataNonEmptyAlternativeForWriterT[F[_], L](implicit + F: NonEmptyAlternative[F], + L: Monoid[L] + ): NonEmptyAlternative[WriterT[F, L, *]] = + new WriterTNonEmptyAlternative[F, L] { + implicit val F0: NonEmptyAlternative[F] = F + implicit val L0: Monoid[L] = L + } + implicit def catsDataMonoidKForWriterT[F[_], L](implicit F: MonoidK[F]): MonoidK[WriterT[F, L, *]] = new WriterTMonoidK[F, L] { implicit val F0: MonoidK[F] = F @@ -739,10 +748,23 @@ sealed private[data] trait WriterTMonoidK[F[_], L] extends MonoidK[WriterT[F, L, def empty[A]: WriterT[F, L, A] = WriterT(F0.empty) } +sealed private[data] trait WriterTNonEmptyAlternative[F[_], L] + extends NonEmptyAlternative[WriterT[F, L, *]] + with WriterTSemigroupK[F, L] + with WriterTApplicative[F, L] { + implicit override def F0: NonEmptyAlternative[F] + + override def prependK[A](a: A, fa: WriterT[F, L, A]): WriterT[F, L, A] = + WriterT(F0.prependK((L0.empty, a), fa.run)) + + override def appendK[A](fa: WriterT[F, L, A], a: A): WriterT[F, L, A] = + WriterT(F0.appendK(fa.run, (L0.empty, a))) +} + sealed private[data] trait WriterTAlternative[F[_], L] extends Alternative[WriterT[F, L, *]] - with WriterTMonoidK[F, L] - with WriterTApplicative[F, L] { + with WriterTNonEmptyAlternative[F, L] + with WriterTMonoidK[F, L] { implicit override def F0: Alternative[F] } diff --git a/tests/shared/src/test/scala/cats/tests/IndexedStateTSuite.scala b/tests/shared/src/test/scala/cats/tests/IndexedStateTSuite.scala index 3983e406cfb..3cf1e0a7dd9 100644 --- a/tests/shared/src/test/scala/cats/tests/IndexedStateTSuite.scala +++ b/tests/shared/src/test/scala/cats/tests/IndexedStateTSuite.scala @@ -509,6 +509,31 @@ class IndexedStateTSuite extends CatsSuite { ) } + { + // F has an NonEmptyAlternative + implicit val G: Monad[ListWrapper] = ListWrapper.monad + implicit val F: NonEmptyAlternative[ListWrapper] = ListWrapper.nonEmptyAlternative + val SA = + IndexedStateT + .catsDataNonEmptyAlternativeForIndexedStateT[ListWrapper, MiniInt](ListWrapper.monad, ListWrapper.alternative) + + implicit val f: Isomorphisms[IndexedStateT[ListWrapper, MiniInt, MiniInt, *]] = Isomorphisms.invariant(SA) + + checkAll( + "IndexedStateT[ListWrapper, MiniInt, Int, Int]", + NonEmptyAlternativeTests[IndexedStateT[ListWrapper, MiniInt, MiniInt, *]](SA).nonEmptyAlternative[Int, Int, Int] + ) + checkAll("Alternative[IndexedStateT[ListWrapper, Int, Int, *]]", SerializableTests.serializable(SA)) + + Monad[IndexedStateT[ListWrapper, Int, Int, *]] + FlatMap[IndexedStateT[ListWrapper, Int, Int, *]] + NonEmptyAlternative[IndexedStateT[ListWrapper, Int, Int, *]] + Applicative[IndexedStateT[ListWrapper, Int, Int, *]] + Apply[IndexedStateT[ListWrapper, Int, Int, *]] + // Functor[IndexedStateT[ListWrapper, Int, Int, *]] + SemigroupK[IndexedStateT[ListWrapper, Int, Int, *]] + } + { // F has an Alternative implicit val G: Monad[ListWrapper] = ListWrapper.monad @@ -526,6 +551,7 @@ class IndexedStateTSuite extends CatsSuite { Monad[IndexedStateT[ListWrapper, Int, Int, *]] FlatMap[IndexedStateT[ListWrapper, Int, Int, *]] + NonEmptyAlternative[IndexedStateT[ListWrapper, Int, Int, *]] Alternative[IndexedStateT[ListWrapper, Int, Int, *]] Applicative[IndexedStateT[ListWrapper, Int, Int, *]] Apply[IndexedStateT[ListWrapper, Int, Int, *]] diff --git a/tests/shared/src/test/scala/cats/tests/KleisliSuite.scala b/tests/shared/src/test/scala/cats/tests/KleisliSuite.scala index ffa679921a0..447648f0bd0 100644 --- a/tests/shared/src/test/scala/cats/tests/KleisliSuite.scala +++ b/tests/shared/src/test/scala/cats/tests/KleisliSuite.scala @@ -23,7 +23,7 @@ package cats.tests import cats._ import cats.arrow._ -import cats.data.{Const, EitherT, Kleisli, Reader, ReaderT} +import cats.data.{Const, EitherT, Kleisli, NonEmptyList, Reader, ReaderT} import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ @@ -124,6 +124,16 @@ class KleisliSuite extends CatsSuite { checkAll("Kleisli[Option, MiniInt, Int]", FlatMapTests[Kleisli[Option, MiniInt, *]].flatMap[Int, Int, Int]) checkAll("FlatMap[Kleisli[Option, Int, *]]", SerializableTests.serializable(FlatMap[Kleisli[Option, Int, *]])) + checkAll("Kleisli[NonEmptyList, MiniInt, *]", + NonEmptyAlternativeTests[Kleisli[NonEmptyList, MiniInt, *]].nonEmptyAlternative[Int, Int, Int] + ) + checkAll("Kleisli[Option, MiniInt, *]", + NonEmptyAlternativeTests[Kleisli[Option, MiniInt, *]].nonEmptyAlternative[Int, Int, Int] + ) + checkAll("NonEmptyAlternative[Kleisli[Option, Int, *]]", + SerializableTests.serializable(NonEmptyAlternative[Kleisli[Option, Int, *]]) + ) + checkAll("Kleisli[Option, MiniInt, *]", AlternativeTests[Kleisli[Option, MiniInt, *]].alternative[Int, Int, Int]) checkAll("Alternative[Kleisli[Option, Int, *]]", SerializableTests.serializable(Alternative[Kleisli[Option, Int, *]])) @@ -395,6 +405,7 @@ class KleisliSuite extends CatsSuite { Functor[Kleisli[List, Int, *]] Apply[Kleisli[List, Int, *]] Applicative[Kleisli[List, Int, *]] + NonEmptyAlternative[Kleisli[NonEmptyList, Int, *]] Alternative[Kleisli[List, Int, *]] Monad[Kleisli[List, Int, *]] Monoid[Kleisli[List, Int, String]] diff --git a/tests/shared/src/test/scala/cats/tests/NestedSuite.scala b/tests/shared/src/test/scala/cats/tests/NestedSuite.scala index 1325d874c26..0cb86db9d1f 100644 --- a/tests/shared/src/test/scala/cats/tests/NestedSuite.scala +++ b/tests/shared/src/test/scala/cats/tests/NestedSuite.scala @@ -205,6 +205,28 @@ class NestedSuite extends CatsSuite { ) } + { + // NonEmptyAlternative composition + implicit val instance: NonEmptyAlternative[ListWrapper] = ListWrapper.nonEmptyAlternative + checkAll("Nested[List, ListWrapper, *]", + NonEmptyAlternativeTests[Nested[List, ListWrapper, *]].nonEmptyAlternative[Int, Int, Int] + ) + checkAll("NonEmptyAlternative[Nested[List, ListWrapper, *]]", + SerializableTests.serializable(NonEmptyAlternative[Nested[List, ListWrapper, *]]) + ) + } + + { + // NonEmptyAlternative for inner Alternative composition (implicits non-abmiguity check) + implicit val instance: Alternative[ListWrapper] = ListWrapper.alternative + checkAll("Nested[List, ListWrapper, *]", + NonEmptyAlternativeTests[Nested[List, ListWrapper, *]].nonEmptyAlternative[Int, Int, Int] + ) + checkAll("NonEmptyAlternative[Nested[List, ListWrapper, *]]", + SerializableTests.serializable(NonEmptyAlternative[Nested[List, ListWrapper, *]]) + ) + } + { // Alternative composition implicit val instance: Alternative[ListWrapper] = ListWrapper.alternative diff --git a/tests/shared/src/test/scala/cats/tests/Tuple2KSuite.scala b/tests/shared/src/test/scala/cats/tests/Tuple2KSuite.scala index ac4f93a032f..747e367f80d 100644 --- a/tests/shared/src/test/scala/cats/tests/Tuple2KSuite.scala +++ b/tests/shared/src/test/scala/cats/tests/Tuple2KSuite.scala @@ -40,6 +40,13 @@ class Tuple2KSuite extends CatsSuite { SerializableTests.serializable(Semigroupal[λ[α => Tuple2K[Option, List, α]]]) ) + checkAll("Tuple2K[Option, List, Int]", + NonEmptyAlternativeTests[λ[α => Tuple2K[Option, List, α]]].nonEmptyAlternative[Int, Int, Int] + ) + checkAll("NonEmptyAlternative[Tuple2K[Option, List, Int]]", + SerializableTests.serializable(NonEmptyAlternative[λ[α => Tuple2K[Option, List, α]]]) + ) + checkAll("Tuple2K[Option, List, Int]", AlternativeTests[λ[α => Tuple2K[Option, List, α]]].alternative[Int, Int, Int]) checkAll("Alternative[Tuple2K[Option, List, Int]]", SerializableTests.serializable(Alternative[λ[α => Tuple2K[Option, List, α]]]) @@ -183,6 +190,18 @@ class Tuple2KSuite extends CatsSuite { ) } + { + implicit val neAlternative: NonEmptyAlternative[ListWrapper] = ListWrapper.nonEmptyAlternative + implicit val iso: Isomorphisms[Tuple2K[ListWrapper, ListWrapper, *]] = + Isomorphisms.invariant[Tuple2K[ListWrapper, ListWrapper, *]] + checkAll("Tuple2K[ListWrapper, ListWrapper, *]", + NonEmptyAlternativeTests[Tuple2K[ListWrapper, ListWrapper, *]].nonEmptyAlternative[Int, Int, Int] + ) + checkAll("NonEmptyAlternative[Tuple2K[ListWrapper, ListWrapper, *]]", + SerializableTests.serializable(NonEmptyAlternative[Tuple2K[ListWrapper, ListWrapper, *]]) + ) + } + { implicit val alternative: Alternative[ListWrapper] = ListWrapper.alternative implicit val iso: Isomorphisms[Tuple2K[ListWrapper, ListWrapper, *]] = diff --git a/tests/shared/src/test/scala/cats/tests/WriterTSuite.scala b/tests/shared/src/test/scala/cats/tests/WriterTSuite.scala index 535d77c7473..3d8687e7846 100644 --- a/tests/shared/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/shared/src/test/scala/cats/tests/WriterTSuite.scala @@ -362,6 +362,25 @@ class WriterTSuite extends CatsSuite { Monad[Logged] } + { + // F has an NonEmptyAlternative and L has a Monoid + implicit val F: NonEmptyAlternative[ListWrapper] = ListWrapper.nonEmptyAlternative + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + + Functor[WriterT[ListWrapper, ListWrapper[Int], *]] + Apply[WriterT[ListWrapper, ListWrapper[Int], *]] + Applicative[WriterT[ListWrapper, ListWrapper[Int], *]] + NonEmptyAlternative[WriterT[ListWrapper, ListWrapper[Int], *]] + CoflatMap[WriterT[ListWrapper, ListWrapper[Int], *]] + checkAll("WriterT[ListWrapper, ListWrapper[Int], *]", + NonEmptyAlternativeTests[WriterT[ListWrapper, ListWrapper[Int], *]].nonEmptyAlternative[Int, Int, Int] + ) + checkAll( + "NonEmptyAlternative[WriterT[ListWrapper, ListWrapper[Int], *]]", + SerializableTests.serializable(NonEmptyAlternative[WriterT[ListWrapper, ListWrapper[Int], *]]) + ) + } + { // F has an Alternative and L has a Monoid implicit val F: Alternative[ListWrapper] = ListWrapper.alternative @@ -370,6 +389,7 @@ class WriterTSuite extends CatsSuite { Functor[WriterT[ListWrapper, ListWrapper[Int], *]] Apply[WriterT[ListWrapper, ListWrapper[Int], *]] Applicative[WriterT[ListWrapper, ListWrapper[Int], *]] + NonEmptyAlternative[WriterT[ListWrapper, ListWrapper[Int], *]] Alternative[WriterT[ListWrapper, ListWrapper[Int], *]] CoflatMap[WriterT[ListWrapper, ListWrapper[Int], *]] checkAll("WriterT[ListWrapper, ListWrapper[Int], *]",