Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SAM syntax for typeclass instances where possible #4279

Merged
merged 13 commits into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ package lattice

import scala.{specialized => sp}

trait BoundedJoinSemilattice[@sp(Int, Long, Float, Double) A] extends Any with JoinSemilattice[A] { self =>
trait BoundedJoinSemilattice[@sp(Int, Long, Float, Double) A] extends Any with JoinSemilattice[A] {
def zero: A
def isZero(a: A)(implicit ev: Eq[A]): Boolean = ev.eqv(a, zero)

override def joinSemilattice: BoundedSemilattice[A] =
new BoundedSemilattice[A] {
def empty: A = self.zero
def empty: A = zero
def combine(x: A, y: A): A = join(x, y)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ package lattice

import scala.{specialized => sp}

trait BoundedMeetSemilattice[@sp(Int, Long, Float, Double) A] extends Any with MeetSemilattice[A] { self =>
trait BoundedMeetSemilattice[@sp(Int, Long, Float, Double) A] extends Any with MeetSemilattice[A] {
def one: A
def isOne(a: A)(implicit ev: Eq[A]): Boolean = ev.eqv(a, one)

override def meetSemilattice: BoundedSemilattice[A] =
new BoundedSemilattice[A] {
def empty: A = self.one
def empty: A = one
def combine(x: A, y: A): A = meet(x, y)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,10 @@ import scala.{specialized => sp}
* operation is called "join", and which can be thought of as a least
* upper bound.
*/
trait JoinSemilattice[@sp(Int, Long, Float, Double) A] extends Any with Serializable { self =>
trait JoinSemilattice[@sp(Int, Long, Float, Double) A] extends Any with Serializable {
def join(lhs: A, rhs: A): A

def joinSemilattice: Semilattice[A] =
new Semilattice[A] {
def combine(x: A, y: A): A = self.join(x, y)
}
def joinSemilattice: Semilattice[A] = join(_, _)

def joinPartialOrder(implicit ev: Eq[A]): PartialOrder[A] =
joinSemilattice.asJoinPartialOrder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,10 @@ import scala.{specialized => sp}
* operation is called "meet", and which can be thought of as a
* greatest lower bound.
*/
trait MeetSemilattice[@sp(Int, Long, Float, Double) A] extends Any with Serializable { self =>
trait MeetSemilattice[@sp(Int, Long, Float, Double) A] extends Any with Serializable {
def meet(lhs: A, rhs: A): A

def meetSemilattice: Semilattice[A] =
new Semilattice[A] {
def combine(x: A, y: A): A = self.meet(x, y)
}
def meetSemilattice: Semilattice[A] = meet(_, _)

def meetPartialOrder(implicit ev: Eq[A]): PartialOrder[A] =
meetSemilattice.asMeetPartialOrder
Expand Down
9 changes: 2 additions & 7 deletions algebra-core/src/main/scala/algebra/ring/Multiplicative.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ import scala.{specialized => sp}
import scala.annotation.{nowarn, tailrec}

trait MultiplicativeSemigroup[@sp(Int, Long, Float, Double) A] extends Any with Serializable {
def multiplicative: Semigroup[A] =
new Semigroup[A] {
def combine(x: A, y: A): A = times(x, y)
}
def multiplicative: Semigroup[A] = times(_, _)

def times(x: A, y: A): A

Expand Down Expand Up @@ -58,9 +55,7 @@ trait MultiplicativeSemigroup[@sp(Int, Long, Float, Double) A] extends Any with
}

trait MultiplicativeCommutativeSemigroup[@sp(Int, Long, Float, Double) A] extends Any with MultiplicativeSemigroup[A] {
override def multiplicative: CommutativeSemigroup[A] = new CommutativeSemigroup[A] {
def combine(x: A, y: A): A = times(x, y)
}
override def multiplicative: CommutativeSemigroup[A] = times(_, _)
}

trait MultiplicativeMonoid[@sp(Int, Long, Float, Double) A] extends Any with MultiplicativeSemigroup[A] {
Expand Down
6 changes: 0 additions & 6 deletions algebra-core/src/test/scala/algebra/Instances.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ package algebra

object Instances {

def t2HasSemigroup[A, B](implicit eva: Semigroup[A], evb: Semigroup[B]) =
new Semigroup[(A, B)] {
def combine(x: (A, B), y: (A, B)): (A, B) =
(eva.combine(x._1, y._1), evb.combine(x._2, y._2))
}

val stringHasMonoid =
new Monoid[String] {
def empty: String = ""
Expand Down
25 changes: 8 additions & 17 deletions algebra-laws/shared/src/test/scala/algebra/laws/FPApprox.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,23 +124,14 @@ object FPApprox {
implicit def fpApproxAlgebra[A: Field: Order: Epsilon]: FPApproxAlgebra[A] = new FPApproxAlgebra[A]

// An Eq instance that returns true if 2 values *could* be equal.
implicit def fpApproxEq[A: Field: Order: Epsilon]: Eq[FPApprox[A]] =
new Eq[FPApprox[A]] {
def eqv(x: FPApprox[A], y: FPApprox[A]): Boolean = {
// We want to check if z +/- error contains 0
if (x.approx == y.approx) {
true
} else {
val z = x - y
val err = z.error
if (Epsilon.isFinite(err)) {
Order.lteqv(Ring[A].minus(z.approx, err), Ring[A].zero) &&
Order.gteqv(Ring[A].plus(z.approx, err), Ring[A].zero)
} else {
true
}
}
}
implicit def fpApproxEq[A: Field: Order: Epsilon]: Eq[FPApprox[A]] = (x, y) =>
// We want to check if z +/- error contains 0
x.approx == y.approx || {
val z = x - y
val err = z.error
!Epsilon.isFinite(err) ||
Order.lteqv(Ring[A].minus(z.approx, err), Ring[A].zero) &&
Order.gteqv(Ring[A].plus(z.approx, err), Ring[A].zero)
}

implicit def arbFPApprox[A: Rng: Order: Arbitrary]: Arbitrary[FPApprox[A]] =
Expand Down
12 changes: 5 additions & 7 deletions algebra-laws/shared/src/test/scala/algebra/laws/LawTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,11 @@ class LawTests extends munit.DisciplineSuite {
implicit val NOrderEq: Eq[Order[N]] = Eq.by { (order: Order[N]) =>
Vector.tabulate(nMax)(N).sorted(order.toOrdering)
}
implicit val NEqEq: Eq[Eq[N]] = new Eq[Eq[N]] {
def eqv(a: Eq[N], b: Eq[N]) =
Iterator
.tabulate(nMax)(N)
.flatMap { x => Iterator.tabulate(nMax)(N).map((x, _)) }
.forall { case (x, y) => a.eqv(x, y) == b.eqv(x, y) }
}
implicit val NEqEq: Eq[Eq[N]] = (a, b) =>
Iterator
.tabulate(nMax)(N)
.flatMap { x => Iterator.tabulate(nMax)(N).map((x, _)) }
.forall { case (x, y) => a.eqv(x, y) == b.eqv(x, y) }

implicit val monoidOrderN: Monoid[Order[N]] = Order.whenEqualMonoid[N]
checkAll("Order[N]", GroupLaws[Order[N]].monoid)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ object SimpleDeMorgan {

implicit val arbitrary: Arbitrary[SimpleDeMorgan] = Arbitrary(oneOf(False, Unknown, True))

implicit val eq: Eq[SimpleDeMorgan] = new Eq[SimpleDeMorgan] {
def eqv(x: SimpleDeMorgan, y: SimpleDeMorgan): Boolean = x == y
}
implicit val eq: Eq[SimpleDeMorgan] =
Eq.fromUniversalEquals
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ object SimpleHeyting {

implicit val arbitrary: Arbitrary[SimpleHeyting] = Arbitrary(oneOf(Zero, Half, One))

implicit val eq: Eq[SimpleHeyting] = new Eq[SimpleHeyting] {
def eqv(x: SimpleHeyting, y: SimpleHeyting): Boolean = x == y
}
implicit val eq: Eq[SimpleHeyting] =
Eq.fromUniversalEquals
}
4 changes: 1 addition & 3 deletions core/src/main/scala-2.12/cats/instances/stream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,7 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {
}

implicit def catsStdShowForStream[A: Show]: Show[Stream[A]] =
new Show[Stream[A]] {
def show(fa: Stream[A]): String = if (fa.isEmpty) "Stream()" else s"Stream(${fa.head.show}, ?)"
}
stream => if (stream.isEmpty) "Stream()" else s"Stream(${stream.head.show}, ?)"

implicit def catsStdParallelForStreamZipStream: Parallel.Aux[Stream, ZipStream] =
new Parallel[Stream] {
Expand Down
3 changes: 1 addition & 2 deletions core/src/main/scala-2.13+/cats/data/NonEmptyLazyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -553,8 +553,7 @@ sealed abstract private[data] class NonEmptyLazyListInstances extends NonEmptyLa
implicit def catsDataSemigroupForNonEmptyLazyList[A]: Semigroup[NonEmptyLazyList[A]] =
Semigroup[LazyList[A]].asInstanceOf[Semigroup[NonEmptyLazyList[A]]]

implicit def catsDataShowForNonEmptyLazyList[A](implicit A: Show[A]): Show[NonEmptyLazyList[A]] =
Show.show[NonEmptyLazyList[A]](_.show)
implicit def catsDataShowForNonEmptyLazyList[A: Show]: Show[NonEmptyLazyList[A]] = _.show

implicit def catsDataParallelForNonEmptyLazyList: Parallel.Aux[NonEmptyLazyList, OneAnd[ZipLazyList, *]] =
new Parallel[NonEmptyLazyList] {
Expand Down
4 changes: 1 addition & 3 deletions core/src/main/scala-2.13+/cats/instances/arraySeq.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ trait ArraySeqInstances extends cats.kernel.instances.ArraySeqInstances {
ArraySeqInstances.stdTraverseFilterInstance

implicit def catsStdShowForArraySeq[A](implicit ev: Show[A]): Show[ArraySeq[A]] =
Show.show { arraySeq =>
arraySeq.iterator.map(ev.show).mkString("ArraySeq(", ", ", ")")
}
_.iterator.map(ev.show).mkString("ArraySeq(", ", ", ")")
}

private[cats] object ArraySeqInstances {
Expand Down
4 changes: 1 addition & 3 deletions core/src/main/scala-2.13+/cats/instances/lazyList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,7 @@ trait LazyListInstances extends cats.kernel.instances.LazyListInstances {
}

implicit def catsStdShowForLazyList[A: Show]: Show[LazyList[A]] =
new Show[LazyList[A]] {
def show(fa: LazyList[A]): String = if (fa.isEmpty) "LazyList()" else s"LazyList(${fa.head.show}, ?)"
}
list => if (list.isEmpty) "LazyList()" else s"LazyList(${list.head.show}, ?)"

implicit val catsStdTraverseFilterForLazyList: TraverseFilter[LazyList] = new TraverseFilter[LazyList] {
val traverse: Traverse[LazyList] = catsStdInstancesForLazyList
Expand Down
4 changes: 1 addition & 3 deletions core/src/main/scala-2.13+/cats/instances/stream.scala
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,7 @@ trait StreamInstances extends cats.kernel.instances.StreamInstances {

@deprecated("Use cats.instances.lazyList", "2.0.0-RC2")
implicit def catsStdShowForStream[A: Show]: Show[Stream[A]] =
new Show[Stream[A]] {
def show(fa: Stream[A]): String = if (fa.isEmpty) "Stream()" else s"Stream(${fa.head.show}, ?)"
}
stream => if (stream.isEmpty) "Stream()" else s"Stream(${stream.head.show}, ?)"

@deprecated("Use catsStdParallelForZipLazyList", "2.0.0-RC2")
implicit def catsStdParallelForStreamZipStream: Parallel.Aux[Stream, ZipStream] =
Expand Down
4 changes: 1 addition & 3 deletions core/src/main/scala/cats/Align.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ trait Align[F[_]] extends Serializable {

object Align extends ScalaVersionSpecificAlignInstances {
def semigroup[F[_], A](implicit F: Align[F], A: Semigroup[A]): Semigroup[F[A]] =
new Semigroup[F[A]] {
def combine(x: F[A], y: F[A]): F[A] = Align[F].alignCombine(x, y)
}
F.alignCombine(_, _)

implicit def catsAlignForList: Align[List] = cats.instances.list.catsStdInstancesForList
implicit def catsAlignForOption: Align[Option] = cats.instances.option.catsStdInstancesForOption
Expand Down
6 changes: 1 addition & 5 deletions core/src/main/scala/cats/CommutativeApply.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ trait CommutativeApply[F[_]] extends Apply[F]

object CommutativeApply {
def commutativeSemigroupFor[F[_]: CommutativeApply, A: CommutativeSemigroup]: CommutativeSemigroup[F[A]] =
new CommutativeSemigroup[F[A]] {
override def combine(x: F[A], y: F[A]): F[A] =
CommutativeApply[F]
.map2(x, y)(CommutativeSemigroup[A].combine)
}
CommutativeApply[F].map2(_, _)(CommutativeSemigroup[A].combine)

/**
* Summon an instance of [[CommutativeApply]] for `F`.
Expand Down
15 changes: 3 additions & 12 deletions core/src/main/scala/cats/Eval.scala
Original file line number Diff line number Diff line change
Expand Up @@ -431,10 +431,7 @@ sealed abstract private[cats] class EvalInstances extends EvalInstances0 {
}

implicit def catsOrderForEval[A: Order]: Order[Eval[A]] =
new Order[Eval[A]] {
def compare(lx: Eval[A], ly: Eval[A]): Int =
Order[A].compare(lx.value, ly.value)
}
Order.by(_.value)

implicit def catsGroupForEval[A: Group]: Group[Eval[A]] =
new EvalGroup[A] { val algebra: Group[A] = Group[A] }
Expand All @@ -458,21 +455,15 @@ sealed abstract private[cats] class EvalInstances extends EvalInstances0 {

sealed abstract private[cats] class EvalInstances0 extends EvalInstances1 {
implicit def catsPartialOrderForEval[A: PartialOrder]: PartialOrder[Eval[A]] =
new PartialOrder[Eval[A]] {
def partialCompare(lx: Eval[A], ly: Eval[A]): Double =
PartialOrder[A].partialCompare(lx.value, ly.value)
}
PartialOrder.by(_.value)

implicit def catsMonoidForEval[A: Monoid]: Monoid[Eval[A]] =
new EvalMonoid[A] { val algebra = Monoid[A] }
}

sealed abstract private[cats] class EvalInstances1 {
implicit def catsEqForEval[A: Eq]: Eq[Eval[A]] =
new Eq[Eval[A]] {
def eqv(lx: Eval[A], ly: Eval[A]): Boolean =
Eq[A].eqv(lx.value, ly.value)
}
Eq.by(_.value)

implicit def catsSemigroupForEval[A: Semigroup]: Semigroup[Eval[A]] =
new EvalSemigroup[A] { val algebra = Semigroup[A] }
Expand Down
7 changes: 2 additions & 5 deletions core/src/main/scala/cats/SemigroupK.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,15 @@ trait SemigroupK[F[_]] extends Serializable { self =>
y.map(yy => combineK(x, yy))

/**
* Given a type A, create a concrete Semigroup[F[A]].
* Given a type A, create a concrete `Semigroup[F[A]]`.
*
* Example:
* {{{
* scala> import cats.implicits._
* 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]] = combineK(_, _)

/**
* "Compose" with a `G[_]` type to form a `SemigroupK` for `λ[α => F[G[α]]]`.
Expand Down
3 changes: 1 addition & 2 deletions core/src/main/scala/cats/Show.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ object Show extends ScalaVersionSpecificShowInstances with ShowInstances {
}

implicit val catsContravariantForShow: Contravariant[Show] = new Contravariant[Show] {
def contramap[A, B](fa: Show[A])(f: B => A): Show[B] =
show[B]((fa.show _).compose(f))
def contramap[A, B](fa: Show[A])(f: B => A): Show[B] = b => fa.show(f(b))
}

implicit def catsShowForUnit: Show[Unit] = cats.instances.unit.catsStdShowForUnit
Expand Down
5 changes: 1 addition & 4 deletions core/src/main/scala/cats/arrow/Compose.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,7 @@ trait Compose[F[_, _]] extends Serializable { self =>
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]] = compose(_, _)
}

object Compose {
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/scala/cats/data/Chain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,8 @@ sealed abstract class Chain[+A] extends ChainCompat[A] {
def hash[AA >: A](implicit hashA: Hash[AA]): Int =
KernelStaticMethods.orderedHash((this: Chain[AA]).iterator)

override def toString: String = show(Show.show[A](_.toString))
override def toString: String =
show(Show.fromToString)

override def equals(o: Any): Boolean =
o match {
Expand Down Expand Up @@ -1320,8 +1321,7 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 {
}
}

implicit def catsDataShowForChain[A](implicit A: Show[A]): Show[Chain[A]] =
Show.show[Chain[A]](_.show)
implicit def catsDataShowForChain[A: Show]: Show[Chain[A]] = _.show

implicit def catsDataOrderForChain[A](implicit A0: Order[A]): Order[Chain[A]] =
new Order[Chain[A]] with ChainPartialOrder[A] {
Expand Down
Loading