diff --git a/core/src/main/scala/cats/MonadCombine.scala b/core/src/main/scala/cats/MonadCombine.scala index 35038f4dac..e57729eafd 100644 --- a/core/src/main/scala/cats/MonadCombine.scala +++ b/core/src/main/scala/cats/MonadCombine.scala @@ -16,6 +16,6 @@ import simulacrum.typeclass */ def unite[G[_], A](fga: F[G[A]])(implicit G: Foldable[G]): F[A] = flatMap(fga) { ga => - G.foldLeft(ga, empty[A])((acc, a) => combine(acc, pure(a))) + G.foldLeft(ga, empty[A])((acc, a) => combineK(acc, pure(a))) } } diff --git a/core/src/main/scala/cats/MonoidK.scala b/core/src/main/scala/cats/MonoidK.scala index b43e23c968..e55077151d 100644 --- a/core/src/main/scala/cats/MonoidK.scala +++ b/core/src/main/scala/cats/MonoidK.scala @@ -35,6 +35,6 @@ import simulacrum.typeclass override def algebra[A]: Monoid[F[A]] = new Monoid[F[A]] { def empty: F[A] = self.empty - def combine(x: F[A], y: F[A]): F[A] = self.combine(x, y) + def combine(x: F[A], y: F[A]): F[A] = self.combineK(x, y) } } diff --git a/core/src/main/scala/cats/SemigroupK.scala b/core/src/main/scala/cats/SemigroupK.scala index adfdb3504b..06f6221d8a 100644 --- a/core/src/main/scala/cats/SemigroupK.scala +++ b/core/src/main/scala/cats/SemigroupK.scala @@ -26,14 +26,14 @@ import simulacrum.{op, typeclass} * Combine two F[A] values. */ @op("<+>", alias=true) - def combine[A](x: F[A], y: F[A]): F[A] + def combineK[A](x: F[A], y: F[A]): F[A] /** * Compose two SemigroupK intsances. */ def compose[G[_]: SemigroupK]: SemigroupK[λ[α => F[G[α]]]] = new SemigroupK[λ[α => F[G[α]]]] { - def combine[A](x: F[G[A]], y: F[G[A]]): F[G[A]] = self.combine(x, y) + def combineK[A](x: F[G[A]], y: F[G[A]]): F[G[A]] = self.combineK(x, y) } /** @@ -41,6 +41,6 @@ import simulacrum.{op, typeclass} */ def algebra[A]: Semigroup[F[A]] = new Semigroup[F[A]] { - def combine(x: F[A], y: F[A]): F[A] = self.combine(x, y) + def combine(x: F[A], y: F[A]): F[A] = self.combineK(x, y) } } diff --git a/core/src/main/scala/cats/arrow/Category.scala b/core/src/main/scala/cats/arrow/Category.scala index 4178141680..fea5703365 100644 --- a/core/src/main/scala/cats/arrow/Category.scala +++ b/core/src/main/scala/cats/arrow/Category.scala @@ -11,7 +11,7 @@ trait Category[F[_, _]] extends Compose[F] { self => override def algebraK: MonoidK[λ[α => F[α, α]]] = new MonoidK[λ[α => F[α, α]]] { def empty[A]: F[A, A] = id - def combine[A](f1: F[A, A], f2: F[A, A]): F[A, A] = self.compose(f1, f2) + def combineK[A](f1: F[A, A], f2: F[A, A]): F[A, A] = self.compose(f1, f2) } override def algebra[A]: Monoid[F[A, A]] = diff --git a/core/src/main/scala/cats/arrow/Compose.scala b/core/src/main/scala/cats/arrow/Compose.scala index dfe4320734..73f5735955 100644 --- a/core/src/main/scala/cats/arrow/Compose.scala +++ b/core/src/main/scala/cats/arrow/Compose.scala @@ -12,7 +12,7 @@ trait Compose[F[_, _]] extends Serializable { self => def algebraK: SemigroupK[λ[α => F[α, α]]] = new SemigroupK[λ[α => F[α, α]]] { - def combine[A](f1: F[A, A], f2: F[A, A]): F[A, A] = self.compose(f1, f2) + def combineK[A](f1: F[A, A], f2: F[A, A]): F[A, A] = self.compose(f1, f2) } def algebra[A]: Semigroup[F[A, A]] = diff --git a/core/src/main/scala/cats/data/Cokleisli.scala b/core/src/main/scala/cats/data/Cokleisli.scala index 749cc2b42e..4aa36b0d55 100644 --- a/core/src/main/scala/cats/data/Cokleisli.scala +++ b/core/src/main/scala/cats/data/Cokleisli.scala @@ -121,7 +121,7 @@ private trait CokleisliProfunctor[F[_]] extends Profunctor[Cokleisli[F, ?, ?]] { private trait CokleisliSemigroupK[F[_]] extends SemigroupK[Lambda[A => Cokleisli[F, A, A]]] { implicit def F: CoflatMap[F] - def combine[A](a: Cokleisli[F, A, A], b: Cokleisli[F, A, A]): Cokleisli[F, A, A] = a compose b + def combineK[A](a: Cokleisli[F, A, A], b: Cokleisli[F, A, A]): Cokleisli[F, A, A] = a compose b } private trait CokleisliMonoidK[F[_]] extends MonoidK[Lambda[A => Cokleisli[F, A, A]]] with CokleisliSemigroupK[F] { diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index d04538eaeb..164285f46d 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -252,7 +252,7 @@ private trait KleisliMonoid[F[_], A, B] extends Monoid[Kleisli[F, A, B]] with Kl private trait KleisliSemigroupK[F[_]] extends SemigroupK[Lambda[A => Kleisli[F, A, A]]] { implicit def F: FlatMap[F] - override def combine[A](a: Kleisli[F, A, A], b: Kleisli[F, A, A]): Kleisli[F, A, A] = a compose b + override def combineK[A](a: Kleisli[F, A, A], b: Kleisli[F, A, A]): Kleisli[F, A, A] = a compose b } private trait KleisliMonoidK[F[_]] extends MonoidK[Lambda[A => Kleisli[F, A, A]]] with KleisliSemigroupK[F] { diff --git a/core/src/main/scala/cats/data/OneAnd.scala b/core/src/main/scala/cats/data/OneAnd.scala index 5500d15548..dd33efaf54 100644 --- a/core/src/main/scala/cats/data/OneAnd.scala +++ b/core/src/main/scala/cats/data/OneAnd.scala @@ -19,21 +19,21 @@ final case class OneAnd[F[_], A](head: A, tail: F[A]) { * Combine the head and tail into a single `F[A]` value. */ def unwrap(implicit F: MonadCombine[F]): F[A] = - F.combine(F.pure(head), tail) + F.combineK(F.pure(head), tail) /** * remove elements not matching the predicate */ def filter(f: A => Boolean)(implicit F: MonadCombine[F]): F[A] = { val rest = F.filter(tail)(f) - if (f(head)) F.combine(F.pure(head), rest) else rest + if (f(head)) F.combineK(F.pure(head), rest) else rest } /** * Append another OneAnd to this */ def combine(other: OneAnd[F, A])(implicit F: MonadCombine[F]): OneAnd[F, A] = - OneAnd(head, F.combine(tail, F.combine(F.pure(other.head), other.tail))) + OneAnd(head, F.combineK(tail, F.combineK(F.pure(other.head), other.tail))) /** * find the first element matching the predicate, if one exists @@ -99,7 +99,7 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority1 { implicit def oneAndSemigroupK[F[_]: MonadCombine]: SemigroupK[OneAnd[F, ?]] = new SemigroupK[OneAnd[F, ?]] { - def combine[A](a: OneAnd[F, A], b: OneAnd[F, A]): OneAnd[F, A] = + def combineK[A](a: OneAnd[F, A], b: OneAnd[F, A]): OneAnd[F, A] = a combine b } @@ -126,10 +126,10 @@ private[data] sealed trait OneAndInstances extends OneAndLowPriority1 { def flatMap[A, B](fa: OneAnd[F, A])(f: A => OneAnd[F, B]): OneAnd[F, B] = { val end = monad.flatMap(fa.tail) { a => val fa = f(a) - monad.combine(monad.pure(fa.head), fa.tail) + monad.combineK(monad.pure(fa.head), fa.tail) } val fst = f(fa.head) - OneAnd(fst.head, monad.combine(fst.tail, end)) + OneAnd(fst.head, monad.combineK(fst.tail, end)) } } } diff --git a/core/src/main/scala/cats/data/Prod.scala b/core/src/main/scala/cats/data/Prod.scala index 3f88eef794..c52d5ee1ad 100644 --- a/core/src/main/scala/cats/data/Prod.scala +++ b/core/src/main/scala/cats/data/Prod.scala @@ -92,8 +92,8 @@ sealed trait ProdApplicative[F[_], G[_]] extends Applicative[Lambda[X => Prod[F, sealed trait ProdSemigroupK[F[_], G[_]] extends SemigroupK[Lambda[X => Prod[F, G, X]]] { def F: SemigroupK[F] def G: SemigroupK[G] - override def combine[A](x: Prod[F, G, A], y: Prod[F, G, A]): Prod[F, G, A] = - Prod(F.combine(x.first, y.first), G.combine(x.second, y.second)) + override def combineK[A](x: Prod[F, G, A], y: Prod[F, G, A]): Prod[F, G, A] = + Prod(F.combineK(x.first, y.first), G.combineK(x.second, y.second)) } sealed trait ProdMonoidK[F[_], G[_]] extends MonoidK[Lambda[X => Prod[F, G, X]]] with ProdSemigroupK[F, G] { diff --git a/core/src/main/scala/cats/data/Streaming.scala b/core/src/main/scala/cats/data/Streaming.scala index 2db7d42f82..2a58376e0b 100644 --- a/core/src/main/scala/cats/data/Streaming.scala +++ b/core/src/main/scala/cats/data/Streaming.scala @@ -866,7 +866,7 @@ private[data] sealed trait StreamingInstances extends StreamingInstances1 { as.flatMap(f) def empty[A]: Streaming[A] = Streaming.empty - def combine[A](xs: Streaming[A], ys: Streaming[A]): Streaming[A] = + def combineK[A](xs: Streaming[A], ys: Streaming[A]): Streaming[A] = xs ++ ys override def map2[A, B, Z](fa: Streaming[A], fb: Streaming[B])(f: (A, B) => Z): Streaming[Z] = diff --git a/core/src/main/scala/cats/data/StreamingT.scala b/core/src/main/scala/cats/data/StreamingT.scala index 3c104fd194..411d45a900 100644 --- a/core/src/main/scala/cats/data/StreamingT.scala +++ b/core/src/main/scala/cats/data/StreamingT.scala @@ -436,7 +436,7 @@ private[data] sealed trait StreamingTInstances extends StreamingTInstances1 { fa.flatMap(f) def empty[A]: StreamingT[F, A] = StreamingT.empty - def combine[A](xs: StreamingT[F, A], ys: StreamingT[F, A]): StreamingT[F, A] = + def combineK[A](xs: StreamingT[F, A], ys: StreamingT[F, A]): StreamingT[F, A] = xs %::: ys override def filter[A](fa: StreamingT[F, A])(f: A => Boolean): StreamingT[F, A] = fa.filter(f) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index dd96735729..0293564fec 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -188,8 +188,8 @@ private[data] sealed trait WriterTMonad[F[_], L] extends WriterTApplicative[F, L private[data] sealed trait WriterTSemigroupK[F[_], L] extends SemigroupK[WriterT[F, L, ?]] { implicit def F0: SemigroupK[F] - def combine[A](x: WriterT[F, L, A], y: WriterT[F, L, A]): WriterT[F, L, A] = - WriterT(F0.combine(x.run, y.run)) + def combineK[A](x: WriterT[F, L, A], y: WriterT[F, L, A]): WriterT[F, L, A] = + WriterT(F0.combineK(x.run, y.run)) } private[data] sealed trait WriterTMonoidK[F[_], L] extends MonoidK[WriterT[F, L, ?]] with WriterTSemigroupK[F, L] { diff --git a/core/src/main/scala/cats/data/XorT.scala b/core/src/main/scala/cats/data/XorT.scala index b50282cfe3..4a4db32744 100644 --- a/core/src/main/scala/cats/data/XorT.scala +++ b/core/src/main/scala/cats/data/XorT.scala @@ -280,7 +280,7 @@ private[data] trait XorTMonadError[F[_], L] extends MonadError[XorT[F, L, ?], L] private[data] trait XorTSemigroupK[F[_], L] extends SemigroupK[XorT[F, L, ?]] { implicit val F: Monad[F] implicit val L: Semigroup[L] - def combine[A](x: XorT[F, L, A], y: XorT[F, L, A]): XorT[F, L, A] = + def combineK[A](x: XorT[F, L, A], y: XorT[F, L, A]): XorT[F, L, A] = XorT(F.flatMap(x.value) { case Xor.Left(l1) => F.map(y.value) { case Xor.Left(l2) => Xor.Left(L.combine(l1, l2)) diff --git a/core/src/main/scala/cats/std/function.scala b/core/src/main/scala/cats/std/function.scala index 8d7c3af2d7..0215fda5b9 100644 --- a/core/src/main/scala/cats/std/function.scala +++ b/core/src/main/scala/cats/std/function.scala @@ -101,7 +101,7 @@ private[std] sealed trait Function1Monoid[A, B] extends Monoid[A => B] with Func } private[std] sealed trait Function1SemigroupK extends SemigroupK[Lambda[A => A => A]] { - override def combine[A](x: A => A, y: A => A): A => A = x compose y + override def combineK[A](x: A => A, y: A => A): A => A = x compose y } private[std] sealed trait Function1MonoidK extends MonoidK[Lambda[A => A => A]] with Function1SemigroupK { diff --git a/core/src/main/scala/cats/std/list.scala b/core/src/main/scala/cats/std/list.scala index 69575cf14e..b7790f9d77 100644 --- a/core/src/main/scala/cats/std/list.scala +++ b/core/src/main/scala/cats/std/list.scala @@ -17,7 +17,7 @@ trait ListInstances extends ListInstances1 { def empty[A]: List[A] = Nil - def combine[A](x: List[A], y: List[A]): List[A] = x ++ y + def combineK[A](x: List[A], y: List[A]): List[A] = x ++ y def pure[A](x: A): List[A] = x :: Nil diff --git a/core/src/main/scala/cats/std/option.scala b/core/src/main/scala/cats/std/option.scala index 4439a4e0a0..05df794fe2 100644 --- a/core/src/main/scala/cats/std/option.scala +++ b/core/src/main/scala/cats/std/option.scala @@ -9,7 +9,7 @@ trait OptionInstances extends OptionInstances1 { def empty[A]: Option[A] = None - def combine[A](x: Option[A], y: Option[A]): Option[A] = x orElse y + def combineK[A](x: Option[A], y: Option[A]): Option[A] = x orElse y def pure[A](x: A): Option[A] = Some(x) diff --git a/core/src/main/scala/cats/std/set.scala b/core/src/main/scala/cats/std/set.scala index 1efeff8350..a4ce9f0bbf 100644 --- a/core/src/main/scala/cats/std/set.scala +++ b/core/src/main/scala/cats/std/set.scala @@ -9,7 +9,7 @@ trait SetInstances extends algebra.std.SetInstances { def empty[A]: Set[A] = Set.empty[A] - def combine[A](x: Set[A], y: Set[A]): Set[A] = x | y + def combineK[A](x: Set[A], y: Set[A]): Set[A] = x | y def foldLeft[A, B](fa: Set[A], b: B)(f: (B, A) => B): B = fa.foldLeft(b)(f) diff --git a/core/src/main/scala/cats/std/stream.scala b/core/src/main/scala/cats/std/stream.scala index 3435e290fc..9406bcec96 100644 --- a/core/src/main/scala/cats/std/stream.scala +++ b/core/src/main/scala/cats/std/stream.scala @@ -10,7 +10,7 @@ trait StreamInstances { def empty[A]: Stream[A] = Stream.Empty - def combine[A](x: Stream[A], y: Stream[A]): Stream[A] = x #::: y + def combineK[A](x: Stream[A], y: Stream[A]): Stream[A] = x #::: y def pure[A](x: A): Stream[A] = Stream(x) diff --git a/core/src/main/scala/cats/std/vector.scala b/core/src/main/scala/cats/std/vector.scala index 88d9797ceb..bb9f0d13e2 100644 --- a/core/src/main/scala/cats/std/vector.scala +++ b/core/src/main/scala/cats/std/vector.scala @@ -10,7 +10,7 @@ trait VectorInstances { def empty[A]: Vector[A] = Vector.empty[A] - def combine[A](x: Vector[A], y: Vector[A]): Vector[A] = x ++ y + def combineK[A](x: Vector[A], y: Vector[A]): Vector[A] = x ++ y def pure[A](x: A): Vector[A] = Vector(x) diff --git a/docs/src/main/tut/semigroupk.md b/docs/src/main/tut/semigroupk.md index 0f3e837883..85a4b4857a 100644 --- a/docs/src/main/tut/semigroupk.md +++ b/docs/src/main/tut/semigroupk.md @@ -64,32 +64,31 @@ takes a concrete type, like `Int`, and returns a concrete type: *`, whereas `Int` would have kind `*` and `Map` would have kind `*,* -> *`, and, in fact, the `K` in `SemigroupK` stands for `Kind`. -For `List`, the `Semigroup` and `SemigroupK` instance's `combine` -operation are both list concatenation: +For `List`, the `Semigroup` instance's `combine` operation and the `SemigroupK` +instance's `combineK` operation are both list concatenation: ```tut -SemigroupK[List].combine(List(1,2,3), List(4,5,6)) == Semigroup[List[Int]].combine(List(1,2,3), List(4,5,6)) +SemigroupK[List].combineK(List(1,2,3), List(4,5,6)) == Semigroup[List[Int]].combine(List(1,2,3), List(4,5,6)) ``` -However for `Option`, `Semigroup` and `SemigroupK`'s `combine` operation -differs. Since `Semigroup` operates on fully specified types, a -`Semigroup[Option[A]]` knows the concrete type of `A` and will -use `Semigroup[A].combine` to combine the inner `A`s. Consequently, -`Semigroup[Option[A]].combine` requires an implicit -`Semigroup[A]`. +However for `Option`, the `Semigroup`'s `combine` and the `SemigroupK`'s +`combineK` operation differ. Since `Semigroup` operates on fully specified +types, a `Semigroup[Option[A]]` knows the concrete type of `A` and will use +`Semigroup[A].combine` to combine the inner `A`s. Consequently, +`Semigroup[Option[A]].combine` requires an implicit `Semigroup[A]`. In contrast, since `SemigroupK[Option]` operates on `Option` where the inner type is not fully specified and can be anything (i.e. is "universally quantified"). Thus, we cannot know how to `combine` two of them. Therefore, in the case of `Option` the -`SemigroupK[Option].combine` method has no choice but to use the +`SemigroupK[Option].combineK` method has no choice but to use the `orElse` method of Option: ```tut Semigroup[Option[Int]].combine(Some(1), Some(2)) -SemigroupK[Option].combine(Some(1), Some(2)) -SemigroupK[Option].combine(Some(1), None) -SemigroupK[Option].combine(None, Some(2)) +SemigroupK[Option].combineK(Some(1), Some(2)) +SemigroupK[Option].combineK(Some(1), None) +SemigroupK[Option].combineK(None, Some(2)) ``` There is inline syntax available for both `Semigroup` and diff --git a/laws/src/main/scala/cats/laws/MonadCombineLaws.scala b/laws/src/main/scala/cats/laws/MonadCombineLaws.scala index 4291bdac53..a8100e381d 100644 --- a/laws/src/main/scala/cats/laws/MonadCombineLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadCombineLaws.scala @@ -10,7 +10,7 @@ trait MonadCombineLaws[F[_]] extends MonadFilterLaws[F] with AlternativeLaws[F] implicit override def F: MonadCombine[F] def monadCombineLeftDistributivity[A, B](fa: F[A], fa2: F[A], f: A => F[B]): IsEq[F[B]] = - F.combine(fa, fa2).flatMap(f) <-> F.combine(fa flatMap f, fa2 flatMap f) + F.combineK(fa, fa2).flatMap(f) <-> F.combineK(fa flatMap f, fa2 flatMap f) } object MonadCombineLaws { diff --git a/laws/src/main/scala/cats/laws/MonoidKLaws.scala b/laws/src/main/scala/cats/laws/MonoidKLaws.scala index c456ee3ddd..8f2f3b600c 100644 --- a/laws/src/main/scala/cats/laws/MonoidKLaws.scala +++ b/laws/src/main/scala/cats/laws/MonoidKLaws.scala @@ -8,10 +8,10 @@ trait MonoidKLaws[F[_]] extends SemigroupKLaws[F] { override implicit def F: MonoidK[F] def monoidKLeftIdentity[A](a: F[A]): IsEq[F[A]] = - F.combine(F.empty, a) <-> a + F.combineK(F.empty, a) <-> a def monoidKRightIdentity[A](a: F[A]): IsEq[F[A]] = - F.combine(a, F.empty) <-> a + F.combineK(a, F.empty) <-> a } object MonoidKLaws { diff --git a/laws/src/main/scala/cats/laws/SemigroupKLaws.scala b/laws/src/main/scala/cats/laws/SemigroupKLaws.scala index 0578f2310c..947e85cf13 100644 --- a/laws/src/main/scala/cats/laws/SemigroupKLaws.scala +++ b/laws/src/main/scala/cats/laws/SemigroupKLaws.scala @@ -8,7 +8,7 @@ trait SemigroupKLaws[F[_]] { implicit def F: SemigroupK[F] def semigroupKAssociative[A](a: F[A], b: F[A], c: F[A]): IsEq[F[A]] = - F.combine(F.combine(a, b), c) <-> F.combine(a, F.combine(b, c)) + F.combineK(F.combineK(a, b), c) <-> F.combineK(a, F.combineK(b, c)) } object SemigroupKLaws { diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 47ffc8e677..74dcfd33c8 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -62,8 +62,8 @@ object ListWrapper { val semigroupK: SemigroupK[ListWrapper] = new SemigroupK[ListWrapper] { - def combine[A](x: ListWrapper[A], y: ListWrapper[A]): ListWrapper[A] = - ListWrapper(SemigroupK[List].combine(x.list, y.list)) + def combineK[A](x: ListWrapper[A], y: ListWrapper[A]): ListWrapper[A] = + ListWrapper(SemigroupK[List].combineK(x.list, y.list)) } def semigroup[A]: Semigroup[ListWrapper[A]] = semigroupK.algebra[A] @@ -79,8 +79,8 @@ object ListWrapper { def empty[A]: ListWrapper[A] = ListWrapper(M.empty[A]) - def combine[A](x: ListWrapper[A], y: ListWrapper[A]): ListWrapper[A] = - ListWrapper(M.combine(x.list, y.list)) + def combineK[A](x: ListWrapper[A], y: ListWrapper[A]): ListWrapper[A] = + ListWrapper(M.combineK(x.list, y.list)) } }