From 4b0a87b70df082848429a8ff623fcf1ab670eb19 Mon Sep 17 00:00:00 2001 From: David Strawn Date: Tue, 15 Nov 2022 15:19:24 -0700 Subject: [PATCH 1/2] Add Syntax For Enumerable Also load the existing definitions PartialNext/PartialPrevious into implicit scope. --- core/src/main/scala/cats/syntax/all.scala | 8 ++ .../main/scala/cats/syntax/enumerable.scala | 78 +++++++++++++++++++ .../main/scala/cats/kernel/Enumerable.scala | 66 ++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 core/src/main/scala/cats/syntax/enumerable.scala diff --git a/core/src/main/scala/cats/syntax/all.scala b/core/src/main/scala/cats/syntax/all.scala index 60d6d2b150..1d92d88c18 100644 --- a/core/src/main/scala/cats/syntax/all.scala +++ b/core/src/main/scala/cats/syntax/all.scala @@ -32,6 +32,7 @@ abstract class AllSyntaxBinCompat with AllSyntaxBinCompat5 with AllSyntaxBinCompat6 with AllSyntaxBinCompat7 + with AllSyntaxBinCompat8 trait AllSyntax extends AlternativeSyntax @@ -122,3 +123,10 @@ trait AllSyntaxBinCompat5 extends ParallelBitraverseSyntax trait AllSyntaxBinCompat6 extends ParallelUnorderedTraverseSyntax trait AllSyntaxBinCompat7 extends SeqSyntax + +trait AllSyntaxBinCompat8 + extends PartialNextSyntax + with NextSyntax + with PartialPreviousSyntax + with PreviousSyntax + with BoundedEnumerableSyntax diff --git a/core/src/main/scala/cats/syntax/enumerable.scala b/core/src/main/scala/cats/syntax/enumerable.scala new file mode 100644 index 0000000000..3e546742b7 --- /dev/null +++ b/core/src/main/scala/cats/syntax/enumerable.scala @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015 Typelevel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package cats +package syntax + +import cats.kernel._ + +trait PartialNextSyntax { + implicit final def catsSyntaxPartialNext[A](a: A): PartialNextOps[A] = + new PartialNextOps(a) +} + +final class PartialNextOps[A](private val lhs: A) extends AnyVal { + def partialNext(implicit A: PartialNext[A]): Option[A] = + A.partialNext(lhs) +} + +trait NextSyntax extends PartialNextSyntax { + implicit final def catsSyntaxNext[A](a: A): NextOps[A] = + new NextOps(a) +} + +final class NextOps[A](private val lhs: A) extends AnyVal { + def next(implicit A: Next[A]): A = + A.next(lhs) +} + +trait PartialPreviousSyntax { + implicit final def catsSyntaxPartialPrevious[A](a: A): PartialPreviousOps[A] = + new PartialPreviousOps(a) +} + +final class PartialPreviousOps[A](private val lhs: A) extends AnyVal { + def partialPrevious(implicit A: PartialPrevious[A]): Option[A] = + A.partialPrevious(lhs) +} + +trait PreviousSyntax extends PartialPreviousSyntax { + implicit final def catsSyntaxPrevious[A](a: A): PreviousOps[A] = + new PreviousOps(a) +} + +final class PreviousOps[A](private val lhs: A) extends AnyVal { + def previous(implicit A: Previous[A]): A = + A.previous(lhs) +} + +trait BoundedEnumerableSyntax extends NextSyntax with PreviousSyntax { + implicit final def catsSyntaxForBoundedEnumerable[A](a: A): BoundedEnumerableOps[A] = + new BoundedEnumerableOps(a) +} + +final class BoundedEnumerableOps[A](private val lhs: A) extends AnyVal { + def cycleNext(implicit A0: PartialNext[A], A1: LowerBounded[A]): A = + A0.partialNext(lhs).getOrElse(A1.minBound) + + def cyclePrevious(implicit A0: PartialPrevious[A], A1: UpperBounded[A]): A = + A0.partialPrevious(lhs).getOrElse(A1.maxBound) +} diff --git a/kernel/src/main/scala/cats/kernel/Enumerable.scala b/kernel/src/main/scala/cats/kernel/Enumerable.scala index d287113d27..6668a4c4b0 100644 --- a/kernel/src/main/scala/cats/kernel/Enumerable.scala +++ b/kernel/src/main/scala/cats/kernel/Enumerable.scala @@ -33,6 +33,29 @@ trait PartialNext[@sp A] { def partialNext(a: A): Option[A] } +object PartialNext { + + def apply[A](implicit A: PartialNext[A]): PartialNext[A] = + A + + implicit def catsKernelPartialNextForUnit: PartialNext[Unit] = + cats.kernel.instances.unit.catsKernelStdOrderForUnit + implicit def catsKernelPartialNextForBoolean: PartialNext[Boolean] = + cats.kernel.instances.boolean.catsKernelStdOrderForBoolean + implicit def catsKernelPartialNextForByte: PartialNext[Byte] = + cats.kernel.instances.byte.catsKernelStdOrderForByte + implicit def catsKernelPartialNextForInt: PartialNext[Int] = + cats.kernel.instances.int.catsKernelStdOrderForInt + implicit def catsKernelPartialNextForShort: PartialNext[Short] = + cats.kernel.instances.short.catsKernelStdOrderForShort + implicit def catsKernelPartialNextForLong: PartialNext[Long] = + cats.kernel.instances.long.catsKernelStdOrderForLong + implicit def catsKernelPartialNextForChar: PartialNext[Char] = + cats.kernel.instances.char.catsKernelStdOrderForChar + implicit def catsKernelPartialNextForBigInt: PartialNext[BigInt] = + cats.kernel.instances.bigInt.catsKernelStdOrderForBigInt +} + /** * A typeclass with an operation which returns a member which is * always greater than the one supplied. @@ -42,6 +65,14 @@ trait Next[@sp A] extends PartialNext[A] { override def partialNext(a: A): Option[A] = Some(next(a)) } +object Next { + def apply[A](implicit A: Next[A]): Next[A] = + A + + implicit def catsKernelNextForBigInt: Next[BigInt] = + cats.kernel.instances.bigInt.catsKernelStdOrderForBigInt +} + /** * A typeclass with an operation which returns a member which is * smaller or `None` than the one supplied. @@ -51,6 +82,28 @@ trait PartialPrevious[@sp A] { def partialPrevious(a: A): Option[A] } +object PartialPrevious { + def apply[A](implicit A: PartialPrevious[A]): PartialPrevious[A] = + A + + implicit def catsKernelPartialPreviousForUnit: PartialPrevious[Unit] = + cats.kernel.instances.unit.catsKernelStdOrderForUnit + implicit def catsKernelPartialPreviousForBoolean: PartialPrevious[Boolean] = + cats.kernel.instances.boolean.catsKernelStdOrderForBoolean + implicit def catsKernelPartialPreviousForByte: PartialPrevious[Byte] = + cats.kernel.instances.byte.catsKernelStdOrderForByte + implicit def catsKernelPartialPreviousForInt: PartialPrevious[Int] = + cats.kernel.instances.int.catsKernelStdOrderForInt + implicit def catsKernelPartialPreviousForShort: PartialPrevious[Short] = + cats.kernel.instances.short.catsKernelStdOrderForShort + implicit def catsKernelPartialPreviousForLong: PartialPrevious[Long] = + cats.kernel.instances.long.catsKernelStdOrderForLong + implicit def catsKernelPartialPreviousForChar: PartialPrevious[Char] = + cats.kernel.instances.char.catsKernelStdOrderForChar + implicit def catsKernelPartialPreviousForBigInt: PartialPrevious[BigInt] = + cats.kernel.instances.bigInt.catsKernelStdOrderForBigInt +} + /** * A typeclass with an operation which returns a member which is * always smaller than the one supplied. @@ -61,6 +114,14 @@ trait Previous[@sp A] extends PartialPrevious[A] { override def partialPrevious(a: A): Option[A] = Some(previous(a)) } +object Previous { + def apply[A](implicit A: Previous[A]): Previous[A] = + A + + implicit def catsKernelPreviousForBigInt: Previous[BigInt] = + cats.kernel.instances.bigInt.catsKernelStdOrderForBigInt +} + /** * A typeclass which has both `previous` and `next` operations * such that `next . previous == identity`. @@ -70,6 +131,11 @@ trait UnboundedEnumerable[@sp A] extends Next[A] with Previous[A] { override def partialOrder: PartialOrder[A] = order } +object UnboundedEnumerable { + def apply[A](implicit A: UnboundedEnumerable[A]): UnboundedEnumerable[A] = + A +} + trait BoundedEnumerable[@sp A] extends PartialPreviousUpperBounded[A] with PartialNextLowerBounded[A] { def order: Order[A] From bf11f760da9db0eb61b8721cb96f8061b56dafab Mon Sep 17 00:00:00 2001 From: David Strawn Date: Wed, 16 Nov 2022 09:48:24 -0700 Subject: [PATCH 2/2] Remove AllSyntaxBinCompat8 --- core/src/main/scala/cats/syntax/all.scala | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/core/src/main/scala/cats/syntax/all.scala b/core/src/main/scala/cats/syntax/all.scala index 1d92d88c18..ba2b3d67fb 100644 --- a/core/src/main/scala/cats/syntax/all.scala +++ b/core/src/main/scala/cats/syntax/all.scala @@ -32,7 +32,6 @@ abstract class AllSyntaxBinCompat with AllSyntaxBinCompat5 with AllSyntaxBinCompat6 with AllSyntaxBinCompat7 - with AllSyntaxBinCompat8 trait AllSyntax extends AlternativeSyntax @@ -86,6 +85,15 @@ trait AllSyntax with ParallelFoldMapASyntax with ParallelTraverseFilterSyntax with ParallelReduceMapASyntax + with PartialNextSyntax + with NextSyntax + with PartialPreviousSyntax + with PreviousSyntax + with BoundedEnumerableSyntax + +// Note, since we dropped 2.11.x support, we no longer need to use bincompat +// traits. All future syntax additions should be added to AllSyntax +// directly. In 3.x.x we should clean this up. trait AllSyntaxBinCompat0 extends UnorderedTraverseSyntax with ApplicativeErrorExtension with TrySyntax @@ -123,10 +131,3 @@ trait AllSyntaxBinCompat5 extends ParallelBitraverseSyntax trait AllSyntaxBinCompat6 extends ParallelUnorderedTraverseSyntax trait AllSyntaxBinCompat7 extends SeqSyntax - -trait AllSyntaxBinCompat8 - extends PartialNextSyntax - with NextSyntax - with PartialPreviousSyntax - with PreviousSyntax - with BoundedEnumerableSyntax