Skip to content

Commit be74ffc

Browse files
committed
Add BoundlessEnumerable, nextOrMin, and previousOrMax
1 parent bbd6664 commit be74ffc

File tree

4 files changed

+53
-6
lines changed

4 files changed

+53
-6
lines changed

kernel/src/main/scala-2.12/cats/kernel/EnumerableCompat.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ package kernel
2525
import scala.{specialized => sp}
2626
import scala.collection.immutable.Stream
2727

28+
@deprecated(message = "Please use Enumerable instead.", since = "2.10.0")
2829
trait PartialPreviousUpperBounded[@sp A] extends PartialPrevious[A] with PartialNext[A] with UpperBounded[A] {
2930

3031
/**
3132
* Enumerate the members in descending order.
3233
*/
34+
@deprecated(message = "Please use Enumerable.membersDescending.", since = "2.10.0")
3335
def membersDescending: Stream[A] = {
3436
def loop(a: A): Stream[A] =
3537
partialPrevious(a) match {
@@ -41,11 +43,13 @@ trait PartialPreviousUpperBounded[@sp A] extends PartialPrevious[A] with Partial
4143

4244
}
4345

46+
@deprecated(message = "Please use Enumerable instead.", since = "2.10.0")
4447
trait PartialNextLowerBounded[@sp A] extends PartialPrevious[A] with PartialNext[A] with LowerBounded[A] {
4548

4649
/**
4750
* Enumerate the members in ascending order.
4851
*/
52+
@deprecated(message = "Please use Enumerable.membersAscending.", since = "2.10.0")
4953
def membersAscending: Stream[A] = {
5054
def loop(a: A): Stream[A] =
5155
partialNext(a) match {

kernel/src/main/scala-2.13+/cats/kernel/EnumerableCompat.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ package kernel
2525
import scala.{specialized => sp}
2626
import scala.collection.immutable.LazyList
2727

28+
@deprecated(message = "Please use Enumerable", since = "2.10.0")
2829
trait PartialPreviousUpperBounded[@sp A] extends PartialPrevious[A] with PartialNext[A] with UpperBounded[A] {
2930

3031
/**
3132
* Enumerate the members in descending order.
3233
*/
34+
@deprecated(message = "Please use Enumerable.membersDescending.", since = "2.10.0")
3335
def membersDescending: LazyList[A] = {
3436
def loop(a: A): LazyList[A] =
3537
partialPrevious(a) match {
@@ -41,11 +43,13 @@ trait PartialPreviousUpperBounded[@sp A] extends PartialPrevious[A] with Partial
4143

4244
}
4345

46+
@deprecated(message = "Please use Enumerable", since = "2.10.0")
4447
trait PartialNextLowerBounded[@sp A] extends PartialPrevious[A] with PartialNext[A] with LowerBounded[A] {
4548

4649
/**
4750
* Enumerate the members in ascending order.
4851
*/
52+
@deprecated(message = "Please use Enumerable.membersAscending.", since = "2.10.0")
4953
def membersAscending: LazyList[A] = {
5054
def loop(a: A): LazyList[A] =
5155
partialNext(a) match {

kernel/src/main/scala/cats/kernel/Enumerable.scala

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import cats.kernel.{ScalaVersionSpecificLazyListCompat => LazyListLike}
4545
trait Enumerable[@sp A] extends PartialNext[A] with PartialPrevious[A]{
4646
def order: Order[A]
4747
def fromEnum(a: A): BigInt
48-
def toEnum(i: BigInt): Option[A]
48+
def toEnumOpt(i: BigInt): Option[A]
4949

5050
/** The fundamental function in the `Enumerable` class. Given a `first`
5151
* element, a second element, and an optional `last` element, enumerate the
@@ -128,7 +128,7 @@ trait Enumerable[@sp A] extends PartialNext[A] with PartialPrevious[A]{
128128
}
129129

130130
def enumFromByToOpt(first: A, step: BigInt, last: Option[A]): LazyListLike.T[A] =
131-
toEnum(step).fold(
131+
toEnumOpt(step).fold(
132132
LazyListLike.empty[A]
133133
)(second =>
134134
enumFromThenToOpt(first, second, last)
@@ -204,6 +204,20 @@ trait Enumerable[@sp A] extends PartialNext[A] with PartialPrevious[A]{
204204
LazyListLike(first)
205205
}
206206

207+
def membersDescending(implicit A: UpperBounded[A]): LazyListLike.T[A] =
208+
partialPrevious(A.maxBound).fold(
209+
LazyListLike.empty[A]
210+
)(previous =>
211+
enumFromThen(A.maxBound, previous)
212+
)
213+
214+
def membersAscending(implicit A: LowerBounded[A]): LazyListLike.T[A] =
215+
partialNext(A.minBound).fold(
216+
LazyListLike.empty[A]
217+
)(next =>
218+
enumFromThen(A.minBound, next)
219+
)
220+
207221
override final def partialOrder: PartialOrder[A] = order
208222
}
209223

@@ -238,6 +252,9 @@ trait PartialNext[@sp A] {
238252

239253
loop(a, n)
240254
}
255+
256+
def nextOrMin(a: A)(implicit A: LowerBounded[A]): A =
257+
partialNext(a).getOrElse(A.minBound)
241258
}
242259

243260
/**
@@ -246,6 +263,10 @@ trait PartialNext[@sp A] {
246263
*/
247264
trait Next[@sp A] extends PartialNext[A] {
248265
def next(a: A): A
266+
267+
override final def nextOrMin(a: A)(implicit A: LowerBounded[A]): A =
268+
next(a)
269+
249270
override def partialNext(a: A): Option[A] = Some(next(a))
250271
}
251272

@@ -276,6 +297,9 @@ trait PartialPrevious[@sp A] {
276297

277298
loop(a, n)
278299
}
300+
301+
def previousOrMax(a: A)(implicit A: UpperBounded[A]): A =
302+
partialPrevious(a).getOrElse(A.maxBound)
279303
}
280304

281305
/**
@@ -285,29 +309,44 @@ trait PartialPrevious[@sp A] {
285309
trait Previous[@sp A] extends PartialPrevious[A] {
286310
def partialOrder: PartialOrder[A]
287311
def previous(a: A): A
312+
313+
override final def previousOrMax(a: A)(implicit A: UpperBounded[A]): A =
314+
previous(a)
315+
288316
override def partialPrevious(a: A): Option[A] = Some(previous(a))
289317
}
290318

291319
/**
292320
* A typeclass which has both `previous` and `next` operations
293321
* such that `next . previous == identity`.
294322
*/
323+
// TODO: Not sure what to do about UnboundedEnumerable. It should extend
324+
// Enumerable, but we can't do that without breaking
325+
// bincompat. BoundlessEnumerable could extened UnboundedEnumerable, but that
326+
// seems silly...
295327
trait UnboundedEnumerable[@sp A] extends Next[A] with Previous[A] {
296328
def order: Order[A]
297329
override def partialOrder: PartialOrder[A] = order
298330
}
299331

332+
trait BoundlessEnumerable[@sp A] extends Enumerable[A] with Next[A] with Previous[A] {
333+
def toEnum(i: BigInt): A
334+
335+
override final def toEnumOpt(i: BigInt): Option[A] = Some(toEnum(i))
336+
}
337+
300338
trait BoundedEnumerable[@sp A] extends PartialPreviousUpperBounded[A] with PartialNextLowerBounded[A] {
301339

302340
def order: Order[A]
303341
override def partialOrder: PartialOrder[A] = order
304342

343+
@deprecated(message = "Please use nextOrMin instead.", since = "2.10.0")
305344
def cycleNext(a: A): A =
306-
partialNext(a).getOrElse(minBound)
345+
nextOrMin(a)(this)
307346

347+
@deprecated(message = "Please use previousOrMax instead.", since = "2.10.0")
308348
def cyclePrevious(a: A): A =
309-
partialPrevious(a).getOrElse(maxBound)
310-
349+
previousOrMax(a)(this)
311350
}
312351

313352
object BoundedEnumerable {

kernel/src/main/scala/cats/kernel/instances/IntInstances.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class IntOrder extends Order[Int] with Hash[Int] with IntBounded with IntEnumera
6767
override val order: Order[Int] = self
6868

6969
override final def fromEnum(a: Int): BigInt = BigInt(a)
70-
override final def toEnum(i: BigInt): Option[Int] =
70+
override final def toEnumOpt(i: BigInt): Option[Int] =
7171
if (i <= BigInt(Int.MaxValue) || i >= BigInt(Int.MinValue)) {
7272
Some(i.toInt)
7373
} else {

0 commit comments

Comments
 (0)