From 585e7553eddc59fb7e9139b71407220be5a88ff8 Mon Sep 17 00:00:00 2001 From: Kory | Ryosuke Kondo Date: Mon, 21 Apr 2025 04:45:10 +0900 Subject: [PATCH 1/5] Weaken some `Alternative` constraints in `OneAnd` --- core/src/main/scala/cats/data/OneAnd.scala | 39 ++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index 06df7e742b..805c27b380 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -34,12 +34,12 @@ import kernel.compat.scalaVersionSpecific.* * type NonEmptyStream[A] = OneAnd[Stream, A] * }}} */ -final case class OneAnd[F[_], A](head: A, tail: F[A]) { +final case class OneAnd[F[_], A](head: A, tail: F[A]) extends OneAndBinCompat0[F, A] { /** * Combine the head and tail into a single `F[A]` value. */ - def unwrap(implicit F: Alternative[F]): F[A] = + def unwrap(implicit F: NonEmptyAlternative[F]): F[A] = F.prependK(head, tail) /** @@ -53,7 +53,7 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) { /** * Append another OneAnd to this */ - def combine(other: OneAnd[F, A])(implicit F: Alternative[F]): OneAnd[F, A] = + def combine(other: OneAnd[F, A])(implicit F: NonEmptyAlternative[F]): OneAnd[F, A] = OneAnd(head, F.combineK(tail, other.unwrap)) /** @@ -123,8 +123,21 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) { s"OneAnd(${A.show(head)}, ${FA.show(tail)})" } +private[data] trait OneAndBinCompat0[F[_], A] { + val head: A + val tail: F[A] + + @deprecated("Kept for binary compatibility", "2.14.0") + private[data] def unwrap(implicit F: Alternative[F]): F[A] = + F.prependK(head, tail) + + @deprecated("Kept for binary compatibility", "2.14.0") + private[data] def combine(other: OneAnd[F, A])(implicit F: Alternative[F]): OneAnd[F, A] = + OneAnd(head, F.combineK(tail, other.unwrap)) +} + @suppressUnusedImportWarningForScalaVersionSpecific -sealed abstract private[data] class OneAndInstances extends OneAndLowPriority0 { +sealed abstract private[data] class OneAndInstances extends OneAndLowPriority0 with OneAndInstancesBinCompat0 { implicit def catsDataParallelForOneAnd[A, M[_]: Alternative, F0[_]: Alternative](implicit P: Parallel.Aux[M, F0] @@ -158,13 +171,13 @@ sealed abstract private[data] class OneAndInstances extends OneAndLowPriority0 { implicit def catsDataShowForOneAnd[A, F[_]](implicit A: Show[A], FA: Show[F[A]]): Show[OneAnd[F, A]] = _.show - implicit def catsDataSemigroupKForOneAnd[F[_]: Alternative]: SemigroupK[OneAnd[F, *]] = + implicit def catsDataSemigroupKForOneAnd[F[_]: NonEmptyAlternative]: SemigroupK[OneAnd[F, *]] = new SemigroupK[OneAnd[F, *]] { def combineK[A](a: OneAnd[F, A], b: OneAnd[F, A]): OneAnd[F, A] = a.combine(b) } - implicit def catsDataSemigroupForOneAnd[F[_]: Alternative, A]: Semigroup[OneAnd[F, A]] = + implicit def catsDataSemigroupForOneAnd[F[_]: NonEmptyAlternative, A]: Semigroup[OneAnd[F, A]] = catsDataSemigroupKForOneAnd[F].algebra implicit def catsDataMonadForOneAnd[F[_]](implicit @@ -331,4 +344,18 @@ sealed abstract private[data] class OneAndLowPriority0 extends OneAndLowPriority } } +private[data] trait OneAndInstancesBinCompat0 { + + @deprecated("Kept for binary compatibility", "2.14.0") + private[data] def catsDataSemigroupKForOneAnd[F[_]: Alternative]: SemigroupK[OneAnd[F, *]] = + new SemigroupK[OneAnd[F, *]] { + def combineK[A](a: OneAnd[F, A], b: OneAnd[F, A]): OneAnd[F, A] = + a.combine(b) + } + + @deprecated("Kept for binary compatibility", "2.14.0") + private[data] def catsDataSemigroupForOneAnd[F[_]: Alternative, A]: Semigroup[OneAnd[F, A]] = + catsDataSemigroupKForOneAnd[F].algebra +} + object OneAnd extends OneAndInstances From c2d14442b3f93f81234ddd12c86bfe42efea54cb Mon Sep 17 00:00:00 2001 From: Kory | Ryosuke Kondo Date: Mon, 21 Apr 2025 05:30:23 +0900 Subject: [PATCH 2/5] Fix bincompat errors the situation looks very similar to https://github.com/typelevel/cats/pull/4055/files#r760450709. --- core/src/main/scala/cats/data/OneAnd.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index 805c27b380..09f87c8fd8 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -347,14 +347,14 @@ sealed abstract private[data] class OneAndLowPriority0 extends OneAndLowPriority private[data] trait OneAndInstancesBinCompat0 { @deprecated("Kept for binary compatibility", "2.14.0") - private[data] def catsDataSemigroupKForOneAnd[F[_]: Alternative]: SemigroupK[OneAnd[F, *]] = + def catsDataSemigroupKForOneAnd[F[_]: Alternative]: SemigroupK[OneAnd[F, *]] = new SemigroupK[OneAnd[F, *]] { def combineK[A](a: OneAnd[F, A], b: OneAnd[F, A]): OneAnd[F, A] = a.combine(b) } @deprecated("Kept for binary compatibility", "2.14.0") - private[data] def catsDataSemigroupForOneAnd[F[_]: Alternative, A]: Semigroup[OneAnd[F, A]] = + def catsDataSemigroupForOneAnd[F[_]: Alternative, A]: Semigroup[OneAnd[F, A]] = catsDataSemigroupKForOneAnd[F].algebra } From af2336602c44baab46691afe1d9a1f568cf174e8 Mon Sep 17 00:00:00 2001 From: Kory | Ryosuke Kondo Date: Thu, 8 May 2025 11:51:20 +0900 Subject: [PATCH 3/5] Make `OneAndBinCompat0` sealed and make use of self-type annotation in response to - https://github.com/typelevel/cats/pull/4739#discussion_r2078617448 - https://github.com/typelevel/cats/pull/4739#discussion_r2078670109 --- core/src/main/scala/cats/data/OneAnd.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index 09f87c8fd8..16d3970def 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -123,10 +123,7 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) extends OneAndBinCompat0[F s"OneAnd(${A.show(head)}, ${FA.show(tail)})" } -private[data] trait OneAndBinCompat0[F[_], A] { - val head: A - val tail: F[A] - +sealed private[data] trait OneAndBinCompat0[F[_], A] { self: OneAnd[F, A] => @deprecated("Kept for binary compatibility", "2.14.0") private[data] def unwrap(implicit F: Alternative[F]): F[A] = F.prependK(head, tail) From 175dd2af979af89b9bfde8f7e318679c1538cd30 Mon Sep 17 00:00:00 2001 From: Kory | Ryosuke Kondo Date: Thu, 8 May 2025 12:00:02 +0900 Subject: [PATCH 4/5] Strip off deprecated annotation and make `OneAndInstancesBinCompat0` sealed --- core/src/main/scala/cats/data/OneAnd.scala | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index 16d3970def..c144a32018 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -124,11 +124,11 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) extends OneAndBinCompat0[F } sealed private[data] trait OneAndBinCompat0[F[_], A] { self: OneAnd[F, A] => - @deprecated("Kept for binary compatibility", "2.14.0") + // Kept for binary compatibility private[data] def unwrap(implicit F: Alternative[F]): F[A] = F.prependK(head, tail) - @deprecated("Kept for binary compatibility", "2.14.0") + // Kept for binary compatibility private[data] def combine(other: OneAnd[F, A])(implicit F: Alternative[F]): OneAnd[F, A] = OneAnd(head, F.combineK(tail, other.unwrap)) } @@ -341,18 +341,18 @@ sealed abstract private[data] class OneAndLowPriority0 extends OneAndLowPriority } } -private[data] trait OneAndInstancesBinCompat0 { +sealed private[data] trait OneAndInstancesBinCompat0 { - @deprecated("Kept for binary compatibility", "2.14.0") - def catsDataSemigroupKForOneAnd[F[_]: Alternative]: SemigroupK[OneAnd[F, *]] = + // Kept for binary compatibility + def catsDataSemigroupKForOneAnd[F[_]](F: Alternative[F]): SemigroupK[OneAnd[F, *]] = new SemigroupK[OneAnd[F, *]] { def combineK[A](a: OneAnd[F, A], b: OneAnd[F, A]): OneAnd[F, A] = - a.combine(b) + a.combine(b)(F) } - @deprecated("Kept for binary compatibility", "2.14.0") - def catsDataSemigroupForOneAnd[F[_]: Alternative, A]: Semigroup[OneAnd[F, A]] = - catsDataSemigroupKForOneAnd[F].algebra + // Kept for binary compatibility + def catsDataSemigroupForOneAnd[F[_], A](F: Alternative[F]): Semigroup[OneAnd[F, A]] = + catsDataSemigroupKForOneAnd[F](F).algebra } object OneAnd extends OneAndInstances From e059ed84494786f5b9fbf2a3e3a604a172fc94e2 Mon Sep 17 00:00:00 2001 From: Kory | Ryosuke Kondo Date: Thu, 8 May 2025 14:08:57 +0900 Subject: [PATCH 5/5] Let superseded methods invoke new implementation through `self` --- core/src/main/scala/cats/data/OneAnd.scala | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index c144a32018..47f52c4b49 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -125,12 +125,12 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) extends OneAndBinCompat0[F sealed private[data] trait OneAndBinCompat0[F[_], A] { self: OneAnd[F, A] => // Kept for binary compatibility - private[data] def unwrap(implicit F: Alternative[F]): F[A] = - F.prependK(head, tail) + private[data] def unwrap(F: Alternative[F]): F[A] = + self.unwrap(F) // Kept for binary compatibility - private[data] def combine(other: OneAnd[F, A])(implicit F: Alternative[F]): OneAnd[F, A] = - OneAnd(head, F.combineK(tail, other.unwrap)) + private[data] def combine(other: OneAnd[F, A])(F: Alternative[F]): OneAnd[F, A] = + self.combine(other)(F) } @suppressUnusedImportWarningForScalaVersionSpecific @@ -341,18 +341,15 @@ sealed abstract private[data] class OneAndLowPriority0 extends OneAndLowPriority } } -sealed private[data] trait OneAndInstancesBinCompat0 { +sealed private[data] trait OneAndInstancesBinCompat0 { self: OneAndInstances => // Kept for binary compatibility def catsDataSemigroupKForOneAnd[F[_]](F: Alternative[F]): SemigroupK[OneAnd[F, *]] = - new SemigroupK[OneAnd[F, *]] { - def combineK[A](a: OneAnd[F, A], b: OneAnd[F, A]): OneAnd[F, A] = - a.combine(b)(F) - } + self.catsDataSemigroupKForOneAnd[F](F) // Kept for binary compatibility def catsDataSemigroupForOneAnd[F[_], A](F: Alternative[F]): Semigroup[OneAnd[F, A]] = - catsDataSemigroupKForOneAnd[F](F).algebra + self.catsDataSemigroupKForOneAnd[F](F).algebra } object OneAnd extends OneAndInstances