Skip to content

Commit

Permalink
add NonEmptyAlternative instance for Cats containers
Browse files Browse the repository at this point in the history
  • Loading branch information
satorg committed Nov 7, 2021
1 parent e156ba4 commit bd6c948
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 30 deletions.
64 changes: 57 additions & 7 deletions core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,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],
Expand Down Expand Up @@ -768,6 +779,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]
Expand Down Expand Up @@ -800,22 +815,34 @@ 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 Alternative[ReaderWriterStateT[F, E, L, S, *]] {
with NonEmptyAlternative[ReaderWriterStateT[F, E, L, S, *]] {

implicit def F: Monad[F]
def G: Alternative[F]
def G: NonEmptyAlternative[F]
implicit def L: Monoid[L]

def empty[A]: ReaderWriterStateT[F, E, L, S, A] = ReaderWriterStateT.liftF(G.empty[A])
// 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] = ReaderWriterStateT.pure[F, E, L, S, A](a)
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] =
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)

override def prependK[A](
a: A,
Expand All @@ -833,3 +860,26 @@ private trait RWSTAlternative1[F[_], E, L, 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]
def G: Alternative[F]
implicit def L: Monoid[L]

def empty[A]: ReaderWriterStateT[F, E, L, S, A] = ReaderWriterStateT.liftF(G.empty[A])

// Must exist in this trait for binary compatibility.
override def pure[A](a: A): ReaderWriterStateT[F, E, L, S, A] =
pure0(a)

// 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] =
ap0(ff)(fa)
}
24 changes: 19 additions & 5 deletions core/src/main/scala/cats/data/IndexedStateT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -278,19 +278,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 }
}
Expand Down Expand Up @@ -486,10 +492,11 @@ 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)
Expand All @@ -499,6 +506,13 @@ sealed abstract private[data] class IndexedStateTAlternative[F[_], S]

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)
Expand Down
20 changes: 16 additions & 4 deletions core/src/main/scala/cats/data/Kleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,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 }

Expand Down Expand Up @@ -581,11 +586,11 @@ 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 KleisliAlternative[F[_], A]
extends Alternative[Kleisli[F, A, *]]
private[data] trait KleisliNonEmptyAlternative[F[_], A]
extends NonEmptyAlternative[Kleisli[F, A, *]]
with KleisliApplicative[F, A]
with KleisliMonoidK[F, A] {
implicit def F: Alternative[F]
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)))
Expand All @@ -594,6 +599,13 @@ private[data] trait KleisliAlternative[F[_], A]
Kleisli(a => F.appendK(fa.run(a), b))
}

private[data] trait KleisliAlternative[F[_], A]
extends Alternative[Kleisli[F, A, *]]
with KleisliNonEmptyAlternative[F, A]
with KleisliMonoidK[F, A] {
implicit def F: Alternative[F]
}

sealed private[data] trait KleisliContravariantMonoidal[F[_], D] extends ContravariantMonoidal[Kleisli[F, D, *]] {
implicit def F: ContravariantMonoidal[F]

Expand Down
21 changes: 17 additions & 4 deletions core/src/main/scala/cats/data/Nested.scala
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,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]
Expand Down Expand Up @@ -301,11 +307,11 @@ 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 NestedAlternative[F[_], G[_]]
extends Alternative[Nested[F, G, *]]
private[data] trait NestedNonEmptyAlternative[F[_], G[_]]
extends NonEmptyAlternative[Nested[F, G, *]]
with NestedApplicative[F, G]
with NestedMonoidK[F, G] {
def FG: Alternative[λ[α => 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))
Expand All @@ -314,6 +320,13 @@ private[data] trait NestedAlternative[F[_], G[_]]
Nested(FG.appendK(fa.value, a))
}

private[data] trait NestedAlternative[F[_], G[_]]
extends Alternative[Nested[F, G, *]]
with NestedNonEmptyAlternative[F, G]
with NestedMonoidK[F, G] {
def FG: Alternative[λ[α => F[G[α]]]]
}

private[data] trait NestedFoldable[F[_], G[_]] extends Foldable[Nested[F, G, *]] {
def FG: Foldable[λ[α => F[G[α]]]]

Expand Down
27 changes: 22 additions & 5 deletions core/src/main/scala/cats/data/Tuple2K.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,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]
Expand Down Expand Up @@ -157,6 +158,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 {
Expand Down Expand Up @@ -334,12 +343,12 @@ sealed private[data] trait Tuple2KMonoidK[F[_], G[_]]
Tuple2K(F.empty[A], G.empty[A])
}

sealed private[data] trait Tuple2KAlternative[F[_], G[_]]
extends Alternative[λ[α => Tuple2K[F, G, α]]]
sealed private[data] trait Tuple2KNonEmptyAlternative[F[_], G[_]]
extends NonEmptyAlternative[λ[α => Tuple2K[F, G, α]]]
with Tuple2KApplicative[F, G]
with Tuple2KMonoidK[F, G] {
def F: Alternative[F]
def G: Alternative[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))
Expand All @@ -348,6 +357,14 @@ sealed private[data] trait Tuple2KAlternative[F[_], G[_]]
Tuple2K(F.appendK(fa.first, a), G.appendK(fa.second, a))
}

sealed private[data] trait Tuple2KAlternative[F[_], G[_]]
extends Alternative[λ[α => Tuple2K[F, G, α]]]
with Tuple2KNonEmptyAlternative[F, G]
with Tuple2KMonoidK[F, G] {
def F: Alternative[F]
def G: Alternative[G]
}

sealed private[data] trait Tuple2KMonad[F[_], G[_]]
extends Monad[λ[α => Tuple2K[F, G, α]]]
with Tuple2KApplicative[F, G] {
Expand Down
24 changes: 20 additions & 4 deletions core/src/main/scala/cats/data/WriterT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,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
Expand Down Expand Up @@ -723,11 +732,11 @@ 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 WriterTAlternative[F[_], L]
extends Alternative[WriterT[F, L, *]]
with WriterTMonoidK[F, L]
sealed private[data] trait WriterTNonEmptyAlternative[F[_], L]
extends NonEmptyAlternative[WriterT[F, L, *]]
with WriterTSemigroupK[F, L]
with WriterTApplicative[F, L] {
implicit override def F0: Alternative[F]
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))
Expand All @@ -736,6 +745,13 @@ sealed private[data] trait WriterTAlternative[F[_], L]
WriterT(F0.appendK(fa.run, (L0.empty, a)))
}

sealed private[data] trait WriterTAlternative[F[_], L]
extends Alternative[WriterT[F, L, *]]
with WriterTNonEmptyAlternative[F, L]
with WriterTMonoidK[F, L] {
implicit override def F0: Alternative[F]
}

sealed private[data] trait WriterTContravariantMonoidal[F[_], L] extends ContravariantMonoidal[WriterT[F, L, *]] {
implicit def F0: ContravariantMonoidal[F]

Expand Down
26 changes: 26 additions & 0 deletions tests/src/test/scala/cats/tests/IndexedStateTSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,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
Expand All @@ -505,6 +530,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, *]]
Expand Down
Loading

0 comments on commit bd6c948

Please sign in to comment.