Skip to content

Commit

Permalink
add NeAlt-ve s12ns for monad transformers
Browse files Browse the repository at this point in the history
  • Loading branch information
satorg committed Sep 17, 2022
1 parent 2e0d307 commit 5d7b27d
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 17 deletions.
6 changes: 6 additions & 0 deletions core/src/main/scala-2.13+/cats/data/ZipLazyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]] =
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/scala-2.13+/cats/data/ZipStream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]] =
Expand Down
77 changes: 71 additions & 6 deletions core/src/main/scala/cats/data/IndexedReaderWriterStateT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand All @@ -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)
}
30 changes: 25 additions & 5 deletions core/src/main/scala/cats/data/IndexedStateT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
Expand Down Expand Up @@ -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)
}
Expand Down
20 changes: 19 additions & 1 deletion core/src/main/scala/cats/data/Kleisli.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 }

Expand Down Expand Up @@ -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]
}
Expand Down
21 changes: 20 additions & 1 deletion core/src/main/scala/cats/data/Nested.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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[α]]]]
}
Expand Down
25 changes: 24 additions & 1 deletion core/src/main/scala/cats/data/Tuple2K.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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]
Expand Down
26 changes: 24 additions & 2 deletions core/src/main/scala/cats/data/WriterT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]
}

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

0 comments on commit 5d7b27d

Please sign in to comment.