Skip to content
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions core/src/main/scala/cats/data/OneAnd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)

/**
Expand All @@ -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))

/**
Expand Down Expand Up @@ -123,8 +123,18 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) {
s"OneAnd(${A.show(head)}, ${FA.show(tail)})"
}

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)

// 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))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While not a requirement, but since there's self: OneAnd in the scope and because Alternative extends NonEmptyAlternative, I wonder if it could be simplified even further:

Suggested change
private[data] def unwrap(implicit F: Alternative[F]): F[A] =
F.prependK(head, tail)
// 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 unwrap(implicit F: Alternative[F]): F[A] =
self.unwrap(F)
// Kept for binary compatibility
private[data] def combine(other: OneAnd[F, A])(F: Alternative[F]): OneAnd[F, A] =
self.combine(other)(F)

Also, I would still recommend to go without implicit parameters here because even though these methods are private[data] they are still visible to Cats' internals and may cause unexpected unexpecties in the future. Not a requirement either, though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I think the same applies to OneAndInstancesBinCompat0 as well, so I made a similar change to the instances trait too (e059ed8).

}

@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]
Expand Down Expand Up @@ -158,13 +168,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
Expand Down Expand Up @@ -331,4 +341,18 @@ sealed abstract private[data] class OneAndLowPriority0 extends OneAndLowPriority
}
}

sealed private[data] trait OneAndInstancesBinCompat0 {

// 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)
}

// Kept for binary compatibility
def catsDataSemigroupForOneAnd[F[_], A](F: Alternative[F]): Semigroup[OneAnd[F, A]] =
catsDataSemigroupKForOneAnd[F](F).algebra
}

object OneAnd extends OneAndInstances