From 4c838994ef13e54ca3d79b6ce3296220b0d7da63 Mon Sep 17 00:00:00 2001 From: Eugene Platonov Date: Tue, 12 Dec 2017 23:42:19 -0500 Subject: [PATCH] Add Semigroup.instance method --- core/src/main/scala/cats/SemigroupK.scala | 5 +---- core/src/main/scala/cats/arrow/Compose.scala | 5 +---- core/src/main/scala/cats/data/Const.scala | 5 ++--- core/src/main/scala/cats/data/Ior.scala | 5 ++--- core/src/main/scala/cats/data/Validated.scala | 4 +--- .../src/main/scala/cats/instances/invariant.scala | 9 +++------ kernel/src/main/scala/cats/kernel/Semigroup.scala | 9 ++++++++- .../main/scala/cats/kernel/instances/either.scala | 15 +++++++-------- 8 files changed, 25 insertions(+), 32 deletions(-) diff --git a/core/src/main/scala/cats/SemigroupK.scala b/core/src/main/scala/cats/SemigroupK.scala index f3ca1b5965..635bfca241 100644 --- a/core/src/main/scala/cats/SemigroupK.scala +++ b/core/src/main/scala/cats/SemigroupK.scala @@ -44,10 +44,7 @@ import simulacrum.typeclass * scala> val s: Semigroup[List[Int]] = SemigroupK[List].algebra[Int] * }}} */ - def algebra[A]: Semigroup[F[A]] = - new Semigroup[F[A]] { - def combine(x: F[A], y: F[A]): F[A] = self.combineK(x, y) - } + def algebra[A]: Semigroup[F[A]] = Semigroup.instance(self.combineK) /** * "Compose" with a `G[_]` type to form a `SemigroupK` for `λ[α => F[G[α]]]`. diff --git a/core/src/main/scala/cats/arrow/Compose.scala b/core/src/main/scala/cats/arrow/Compose.scala index f5e210332e..b9b8a6a18a 100644 --- a/core/src/main/scala/cats/arrow/Compose.scala +++ b/core/src/main/scala/cats/arrow/Compose.scala @@ -33,8 +33,5 @@ import simulacrum.typeclass 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]] = - new Semigroup[F[A, A]] { - def combine(f1: F[A, A], f2: F[A, A]): F[A, A] = self.compose(f1, f2) - } + def algebra[A]: Semigroup[F[A, A]] = Semigroup.instance(self.compose) } diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala index b076870bdf..0f2fe94821 100644 --- a/core/src/main/scala/cats/data/Const.scala +++ b/core/src/main/scala/cats/data/Const.scala @@ -105,9 +105,8 @@ private[data] sealed abstract class ConstInstances extends ConstInstances0 { } private[data] sealed abstract class ConstInstances0 extends ConstInstances1 { - implicit def catsDataSemigroupForConst[A: Semigroup, B]: Semigroup[Const[A, B]] = new Semigroup[Const[A, B]] { - def combine(x: Const[A, B], y: Const[A, B]): Const[A, B] = x combine y - } + implicit def catsDataSemigroupForConst[A: Semigroup, B]: Semigroup[Const[A, B]] = + Semigroup.instance(_ combine _) implicit def catsDataContravariantForConst[C]: Contravariant[Const[C, ?]] = new Contravariant[Const[C, ?]] { override def contramap[A, B](fa: Const[C, A])(f: (B) => A): Const[C, B] = diff --git a/core/src/main/scala/cats/data/Ior.scala b/core/src/main/scala/cats/data/Ior.scala index 6ffa11e82b..ffcabc13df 100644 --- a/core/src/main/scala/cats/data/Ior.scala +++ b/core/src/main/scala/cats/data/Ior.scala @@ -153,9 +153,8 @@ private[data] sealed abstract class IorInstances extends IorInstances0 { def show(f: A Ior B): String = f.show } - implicit def catsDataSemigroupForIor[A: Semigroup, B: Semigroup]: Semigroup[Ior[A, B]] = new Semigroup[Ior[A, B]] { - def combine(x: Ior[A, B], y: Ior[A, B]) = x.combine(y) - } + implicit def catsDataSemigroupForIor[A: Semigroup, B: Semigroup]: Semigroup[Ior[A, B]] = + Semigroup.instance(_ combine _) implicit def catsDataMonadErrorForIor[A: Semigroup]: MonadError[Ior[A, ?], A] = new MonadError[Ior[A, ?], A] { diff --git a/core/src/main/scala/cats/data/Validated.scala b/core/src/main/scala/cats/data/Validated.scala index 4cc8d56884..d0fb1625ce 100644 --- a/core/src/main/scala/cats/data/Validated.scala +++ b/core/src/main/scala/cats/data/Validated.scala @@ -419,9 +419,7 @@ private[data] sealed abstract class ValidatedInstances extends ValidatedInstance private[data] sealed abstract class ValidatedInstances1 extends ValidatedInstances2 { implicit def catsDataSemigroupForValidated[A, B](implicit A: Semigroup[A], B: Semigroup[B]): Semigroup[Validated[A, B]] = - new Semigroup[Validated[A, B]] { - def combine(x: Validated[A, B], y: Validated[A, B]): Validated[A, B] = x combine y - } + Semigroup.instance(_ combine _) implicit def catsDataCommutativeApplicativeForValidated[E: CommutativeSemigroup]: CommutativeApplicative[Validated[E, ?]] = new ValidatedApplicative[E] with CommutativeApplicative[Validated[E, ?]] diff --git a/core/src/main/scala/cats/instances/invariant.scala b/core/src/main/scala/cats/instances/invariant.scala index c2e9a968bb..061aa9c3d0 100644 --- a/core/src/main/scala/cats/instances/invariant.scala +++ b/core/src/main/scala/cats/instances/invariant.scala @@ -6,9 +6,8 @@ import cats.InvariantMonoidal trait InvariantMonoidalInstances { implicit val catsInvariantMonoidalSemigroup: InvariantMonoidal[Semigroup] = new InvariantMonoidal[Semigroup] { - def product[A, B](fa: Semigroup[A], fb: Semigroup[B]): Semigroup[(A, B)] = new Semigroup[(A, B)] { - def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2) - } + def product[A, B](fa: Semigroup[A], fb: Semigroup[B]): Semigroup[(A, B)] = + Semigroup.instance { (x, y) => fa.combine(x._1, y._1) -> fb.combine(x._2, y._2) } def imap[A, B](fa: Semigroup[A])(f: A => B)(g: B => A): Semigroup[B] = new Semigroup[B] { def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) @@ -19,9 +18,7 @@ trait InvariantMonoidalInstances { def pure[A](a: A): Semigroup[A] = new Semigroup[A] { def combine(x: A, y: A): A = a override def combineAllOption(as: TraversableOnce[A]): Option[A] = - if (as.isEmpty) None - else if (as.size == 1) as.toList.headOption - else Some(a) + if (as.size > 1) Some(a) else as.toTraversable.headOption } } diff --git a/kernel/src/main/scala/cats/kernel/Semigroup.scala b/kernel/src/main/scala/cats/kernel/Semigroup.scala index e05407fdde..807af3d2e3 100644 --- a/kernel/src/main/scala/cats/kernel/Semigroup.scala +++ b/kernel/src/main/scala/cats/kernel/Semigroup.scala @@ -1,7 +1,7 @@ package cats.kernel import scala.{ specialized => sp } -import scala.annotation.{ tailrec } +import scala.annotation.tailrec /** * A semigroup is any set `A` with an associative operation (`combine`). @@ -76,4 +76,11 @@ object Semigroup extends SemigroupFunctions[Semigroup] { * Access an implicit `Semigroup[A]`. */ @inline final def apply[A](implicit ev: Semigroup[A]): Semigroup[A] = ev + + /** + * Create a `Semigroup` instance from a function. + */ + @inline def instance[A](cmb: (A, A) => A): Semigroup[A] = new Semigroup[A] { + override def combine(x: A, y: A): A = cmb(x, y) + } } diff --git a/kernel/src/main/scala/cats/kernel/instances/either.scala b/kernel/src/main/scala/cats/kernel/instances/either.scala index bf71f23389..134bddd482 100644 --- a/kernel/src/main/scala/cats/kernel/instances/either.scala +++ b/kernel/src/main/scala/cats/kernel/instances/either.scala @@ -38,15 +38,14 @@ trait EitherInstances extends EitherInstances0 { trait EitherInstances0 extends EitherInstances1 { implicit def catsDataSemigroupForEither[A, B](implicit B: Semigroup[B]): Semigroup[Either[A, B]] = - new Semigroup[Either[A, B]] { - def combine(x: Either[A, B], y: Either[A, B]): Either[A, B] = - x match { - case left @ Left(_) => left - case Right(xx) => y match { - case left @ Left(_) => left - case Right(yy) => Right(B.combine(xx, yy)) - } + Semigroup.instance { (x, y) => + x match { + case left@Left(_) => left + case Right(xx) => y match { + case left@Left(_) => left + case Right(yy) => Right(B.combine(xx, yy)) } + } } implicit def catsStdPartialOrderForEither[A, B](implicit A: PartialOrder[A], B: PartialOrder[B]): PartialOrder[Either[A, B]] =