Skip to content

Commit

Permalink
Move appropriate SortedSet and SortedMap instances to kernel (#3001)
Browse files Browse the repository at this point in the history
* Move appropriate SortedSet and SortedMap instances to kernel

* Make new prioritization traits package-private
  • Loading branch information
travisbrown authored and LukaJCB committed Aug 23, 2019
1 parent 4cece15 commit a7373fe
Show file tree
Hide file tree
Showing 15 changed files with 264 additions and 111 deletions.
2 changes: 2 additions & 0 deletions core/src/main/scala-2.12-/cats/instances/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@ private[cats] trait AllInstancesBinCompat3 extends AllCoreDurationInstances
private[cats] trait AllInstancesBinCompat4 extends SortedMapInstancesBinCompat1 with MapInstancesBinCompat1

private[cats] trait AllInstancesBinCompat5 extends SortedSetInstancesBinCompat0

private[cats] trait AllInstancesBinCompat6 extends SortedSetInstancesBinCompat1 with SortedMapInstancesBinCompat2
9 changes: 7 additions & 2 deletions core/src/main/scala-2.12-/cats/instances/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package object instances {
with AllInstancesBinCompat3
with AllInstancesBinCompat4
with AllInstancesBinCompat5
with AllInstancesBinCompat6
object bigInt extends BigIntInstances
object bigDecimal extends BigDecimalInstances
object bitSet extends BitSetInstances
Expand Down Expand Up @@ -38,8 +39,12 @@ package object instances {
object queue extends QueueInstances
object set extends SetInstances
object short extends ShortInstances
object sortedMap extends SortedMapInstances with SortedMapInstancesBinCompat0 with SortedMapInstancesBinCompat1
object sortedSet extends SortedSetInstances with SortedSetInstancesBinCompat0
object sortedMap
extends SortedMapInstances
with SortedMapInstancesBinCompat0
with SortedMapInstancesBinCompat1
with SortedMapInstancesBinCompat2
object sortedSet extends SortedSetInstances with SortedSetInstancesBinCompat0 with SortedSetInstancesBinCompat1
object stream extends StreamInstances with StreamInstancesBinCompat0
object string extends StringInstances
object try_ extends TryInstances
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/scala-2.13+/cats/instances/all.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ private[cats] trait AllInstancesBinCompat3 extends AllCoreDurationInstances
private[cats] trait AllInstancesBinCompat4 extends SortedMapInstancesBinCompat1 with MapInstancesBinCompat1

private[cats] trait AllInstancesBinCompat5 extends SortedSetInstancesBinCompat0

private[cats] trait AllInstancesBinCompat6 extends SortedSetInstancesBinCompat1 with SortedMapInstancesBinCompat2
9 changes: 7 additions & 2 deletions core/src/main/scala-2.13+/cats/instances/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package object instances {
with AllInstancesBinCompat3
with AllInstancesBinCompat4
with AllInstancesBinCompat5
with AllInstancesBinCompat6
object bigInt extends BigIntInstances
object bigDecimal extends BigDecimalInstances
object bitSet extends BitSetInstances
Expand Down Expand Up @@ -38,8 +39,12 @@ package object instances {
object queue extends QueueInstances
object set extends SetInstances
object short extends ShortInstances
object sortedMap extends SortedMapInstances with SortedMapInstancesBinCompat0 with SortedMapInstancesBinCompat1
object sortedSet extends SortedSetInstances with SortedSetInstancesBinCompat0
object sortedMap
extends SortedMapInstances
with SortedMapInstancesBinCompat0
with SortedMapInstancesBinCompat1
with SortedMapInstancesBinCompat2
object sortedSet extends SortedSetInstances with SortedSetInstancesBinCompat0 with SortedSetInstancesBinCompat1

@deprecated("Use cats.instances.lazyList", "2.0.0-RC2")
object stream extends StreamInstances with StreamInstancesBinCompat0
Expand Down
85 changes: 25 additions & 60 deletions core/src/main/scala/cats/instances/sortedMap.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ package cats.instances

import cats.{Always, Applicative, Eval, FlatMap, Foldable, Monoid, MonoidK, Order, Show, Traverse, TraverseFilter}
import cats.kernel._
import cats.kernel.instances.StaticMethods

import scala.annotation.tailrec
import scala.collection.immutable.SortedMap

trait SortedMapInstances extends SortedMapInstances2 {

implicit def catsStdHashForSortedMap[K: Hash: Order, V: Hash]: Hash[SortedMap[K, V]] =
new SortedMapHash[K, V]
@deprecated("2.0.0-RC2", "Use cats.kernel.instances.sortedMap.catsKernelStdHashForSortedMap")
private[instances] def catsStdHashForSortedMap[K: Hash: Order, V: Hash]: Hash[SortedMap[K, V]] =
cats.kernel.instances.sortedMap.catsKernelStdHashForSortedMap[K, V]

implicit def catsStdCommutativeMonoidForSortedMap[K: Order, V: CommutativeSemigroup]
: CommutativeMonoid[SortedMap[K, V]] =
new SortedMapCommutativeMonoid[K, V]
@deprecated("2.0.0-RC2", "Use cats.kernel.instances.sortedMap.catsKernelStdCommutativeMonoidForSortedMap")
private[instances] def catsStdCommutativeMonoidForSortedMap[K: Order, V: CommutativeSemigroup] =
cats.kernel.instances.sortedMap.catsKernelStdCommutativeMonoidForSortedMap[K, V]

implicit def catsStdShowForSortedMap[A: Order, B](implicit showA: Show[A], showB: Show[B]): Show[SortedMap[A, B]] =
new Show[SortedMap[A, B]] {
Expand Down Expand Up @@ -114,76 +114,39 @@ trait SortedMapInstances extends SortedMapInstances2 {
}

private[instances] trait SortedMapInstances1 {
implicit def catsStdEqForSortedMap[K: Order, V: Eq]: Eq[SortedMap[K, V]] =
@deprecated("2.0.0-RC2", "Use cats.kernel.instances.sortedMap.catsKernelStdEqForSortedMap")
private[instances] def catsStdEqForSortedMap[K: Order, V: Eq]: Eq[SortedMap[K, V]] =
new SortedMapEq[K, V]
}

private[instances] trait SortedMapInstances2 extends SortedMapInstances1 {
implicit def catsStdMonoidForSortedMap[K: Order, V: Semigroup]: Monoid[SortedMap[K, V]] =
@deprecated("2.0.0-RC2", "Use cats.kernel.instances.sortedMap.catsKernelStdMonoidForSortedMap")
private[instances] def catsStdMonoidForSortedMap[K: Order, V: Semigroup]: Monoid[SortedMap[K, V]] =
new SortedMapMonoid[K, V]
}

@deprecated("2.0.0-RC2", "Use cats.kernel.instances.SortedMapHash")
class SortedMapHash[K, V](implicit V: Hash[V], O: Order[K], K: Hash[K])
extends SortedMapEq[K, V]()(V, O)
extends SortedMapEq[K, V]
with Hash[SortedMap[K, V]] {
// adapted from [[scala.util.hashing.MurmurHash3]],
// but modified standard `Any#hashCode` to `ev.hash`.
import scala.util.hashing.MurmurHash3._
def hash(x: SortedMap[K, V]): Int = {
var a, b, n = 0
var c = 1
x.foreach {
case (k, v) =>
val h = StaticMethods.product2HashWithPrefix(K.hash(k), V.hash(v), "Tuple2")
a += h
b ^= h
c = StaticMethods.updateUnorderedHashC(c, h)
n += 1
}
var h = mapSeed
h = mix(h, a)
h = mix(h, b)
h = mixLast(h, c)
finalizeHash(h, n)
}
private[this] val underlying: Hash[SortedMap[K, V]] = new cats.kernel.instances.SortedMapHash[K, V]
def hash(x: SortedMap[K, V]): Int = underlying.hash(x)
}

class SortedMapEq[K, V](implicit V: Eq[V], O: Order[K]) extends Eq[SortedMap[K, V]] {
def eqv(x: SortedMap[K, V], y: SortedMap[K, V]): Boolean =
if (x eq y) true
else
x.size == y.size && x.forall {
case (k, v1) =>
y.get(k) match {
case Some(v2) => V.eqv(v1, v2)
case None => false
}
}
}
@deprecated("2.0.0-RC2", "Use cats.kernel.instances.SortedMapEq")
class SortedMapEq[K, V](implicit V: Eq[V], O: Order[K]) extends cats.kernel.instances.SortedMapEq[K, V]

@deprecated("2.0.0-RC2", "Use cats.kernel.instances.SortedMapCommutativeMonoid")
class SortedMapCommutativeMonoid[K, V](implicit V: CommutativeSemigroup[V], O: Order[K])
extends SortedMapMonoid[K, V]
with CommutativeMonoid[SortedMap[K, V]]

class SortedMapMonoid[K, V](implicit V: Semigroup[V], O: Order[K]) extends Monoid[SortedMap[K, V]] {

def empty: SortedMap[K, V] = SortedMap.empty(O.toOrdering)

def combine(xs: SortedMap[K, V], ys: SortedMap[K, V]): SortedMap[K, V] =
if (xs.size <= ys.size) {
xs.foldLeft(ys) {
case (my, (k, x)) =>
my.updated(k, Semigroup.maybeCombine(x, my.get(k)))
}
} else {
ys.foldLeft(xs) {
case (mx, (k, y)) =>
mx.updated(k, Semigroup.maybeCombine(mx.get(k), y))
}
}

with CommutativeMonoid[SortedMap[K, V]] {
private[this] val underlying: CommutativeMonoid[SortedMap[K, V]] =
new cats.kernel.instances.SortedMapCommutativeMonoid[K, V]
}

@deprecated("2.0.0-RC2", "Use cats.kernel.instances.SortedMapMonoid")
class SortedMapMonoid[K, V](implicit V: Semigroup[V], O: Order[K]) extends cats.kernel.instances.SortedMapMonoid[K, V]

private[instances] trait SortedMapInstancesBinCompat0 {
implicit def catsStdTraverseFilterForSortedMap[K: Order]: TraverseFilter[SortedMap[K, *]] =
new TraverseFilter[SortedMap[K, *]] {
Expand Down Expand Up @@ -231,3 +194,5 @@ private[instances] trait SortedMapInstancesBinCompat1 {
override def combineK[A](x: SortedMap[K, A], y: SortedMap[K, A]): SortedMap[K, A] = x ++ y
}
}

private[instances] trait SortedMapInstancesBinCompat2 extends cats.kernel.instances.SortedMapInstances
75 changes: 30 additions & 45 deletions core/src/main/scala/cats/instances/sortedSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ package cats
package instances

import cats.kernel.{BoundedSemilattice, Hash, Order}
import cats.kernel.instances.StaticMethods
import scala.collection.immutable.SortedSet
import scala.annotation.tailrec
import cats.implicits._

trait SortedSetInstances extends SortedSetInstances1 {

Expand Down Expand Up @@ -64,19 +62,22 @@ trait SortedSetInstances extends SortedSetInstances1 {

implicit def catsStdShowForSortedSet[A: Show]: Show[SortedSet[A]] = new Show[SortedSet[A]] {
def show(fa: SortedSet[A]): String =
fa.iterator.map(_.show).mkString("SortedSet(", ", ", ")")
fa.iterator.map(Show[A].show).mkString("SortedSet(", ", ", ")")
}

implicit def catsKernelStdOrderForSortedSet[A: Order]: Order[SortedSet[A]] =
new SortedSetOrder[A]
@deprecated("2.0.0-RC2", "Use cats.kernel.instances.sortedSet.catsKernelStdOrderForSortedSet")
private[instances] def catsKernelStdOrderForSortedSet[A: Order]: Order[SortedSet[A]] =
cats.kernel.instances.sortedSet.catsKernelStdOrderForSortedSet[A]
}

private[instances] trait SortedSetInstances1 {
implicit def catsKernelStdHashForSortedSet[A: Order: Hash]: Hash[SortedSet[A]] =
new SortedSetHash[A]
@deprecated("2.0.0-RC2", "Use cats.kernel.instances.sortedSet.catsKernelStdHashForSortedSet")
private[instances] def catsKernelStdHashForSortedSet[A: Order: Hash]: Hash[SortedSet[A]] =
cats.kernel.instances.sortedSet.catsKernelStdHashForSortedSet[A]

implicit def catsKernelStdSemilatticeForSortedSet[A: Order]: BoundedSemilattice[SortedSet[A]] =
new SortedSetSemilattice[A]
@deprecated("2.0.0-RC2", "Use cats.kernel.instances.sortedSet.catsKernelStdSemilatticeForSortedSet")
private[instances] def catsKernelStdSemilatticeForSortedSet[A: Order]: BoundedSemilattice[SortedSet[A]] =
cats.kernel.instances.sortedSet.catsKernelStdBoundedSemilatticeForSortedSet[A]
}

private[instances] trait SortedSetInstancesBinCompat0 {
Expand All @@ -90,43 +91,27 @@ private[instances] trait SortedSetInstancesBinCompat0 {
}
}

class SortedSetOrder[A: Order] extends Order[SortedSet[A]] {
def compare(a1: SortedSet[A], a2: SortedSet[A]): Int =
Order[Int].compare(a1.size, a2.size) match {
case 0 => StaticMethods.iteratorCompare(a1.iterator, a2.iterator)
case x => x
}

override def eqv(s1: SortedSet[A], s2: SortedSet[A]): Boolean =
StaticMethods.iteratorEq(s1.iterator, s2.iterator)
private[instances] trait SortedSetInstancesBinCompat1 extends LowPrioritySortedSetInstancesBinCompat1 {
// TODO: Remove when this is no longer necessary for binary compatibility.
implicit override def catsKernelStdHashForSortedSet[A: Order: Hash]: Hash[SortedSet[A]] =
cats.kernel.instances.sortedSet.catsKernelStdHashForSortedSet[A]
}

class SortedSetHash[A: Order: Hash] extends Hash[SortedSet[A]] {
import scala.util.hashing.MurmurHash3._

// adapted from [[scala.util.hashing.MurmurHash3]],
// but modified standard `Any#hashCode` to `ev.hash`.
def hash(xs: SortedSet[A]): Int = {
var a, b, n = 0
var c = 1
xs.foreach { x =>
val h = Hash[A].hash(x)
a += h
b ^= h
c = cats.kernel.instances.StaticMethods.updateUnorderedHashC(c, h)
n += 1
}
var h = setSeed
h = mix(h, a)
h = mix(h, b)
h = mixLast(h, c)
finalizeHash(h, n)
}
override def eqv(s1: SortedSet[A], s2: SortedSet[A]): Boolean =
StaticMethods.iteratorEq(s1.iterator, s2.iterator)(Order[A])
}
private[instances] trait LowPrioritySortedSetInstancesBinCompat1
extends cats.kernel.instances.SortedSetInstances
with SortedSetInstances {
implicit override def catsKernelStdOrderForSortedSet[A: Order]: Order[SortedSet[A]] =
cats.kernel.instances.sortedSet.catsKernelStdOrderForSortedSet[A]

class SortedSetSemilattice[A: Order] extends BoundedSemilattice[SortedSet[A]] {
def empty: SortedSet[A] = SortedSet.empty(implicitly[Order[A]].toOrdering)
def combine(x: SortedSet[A], y: SortedSet[A]): SortedSet[A] = x | y
override def catsKernelStdHashForSortedSet[A: Order: Hash]: Hash[SortedSet[A]] =
cats.kernel.instances.sortedSet.catsKernelStdHashForSortedSet[A]
}

@deprecated("2.0.0-RC2", "Use cats.kernel.instances.SortedSetHash")
class SortedSetHash[A: Order: Hash] extends cats.kernel.instances.SortedSetHash[A]

@deprecated("2.0.0-RC2", "Use cats.kernel.instances.SortedSetOrder")
class SortedSetOrder[A: Order] extends cats.kernel.instances.SortedSetOrder[A]

@deprecated("2.0.0-RC2", "Use cats.kernel.instances.SortedSetSemilattice")
class SortedSetSemilattice[A: Order] extends cats.kernel.instances.SortedSetSemilattice[A]
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import org.scalactic.anyvals.{PosInt, PosZInt}
import org.scalatest.funsuite.AnyFunSuiteLike

import scala.concurrent.duration.{Duration, FiniteDuration}
import scala.collection.immutable.{BitSet, Queue}
import scala.collection.immutable.{BitSet, Queue, SortedMap, SortedSet}
import scala.util.Random
import java.util.UUID
import java.util.concurrent.TimeUnit.{DAYS, HOURS, MICROSECONDS, MILLISECONDS, MINUTES, NANOSECONDS, SECONDS}
Expand Down Expand Up @@ -64,6 +64,28 @@ object KernelCheck {
)
}

// Copied from cats-laws.
implicit def arbitrarySortedMap[K: Arbitrary: Order, V: Arbitrary]: Arbitrary[SortedMap[K, V]] =
Arbitrary(arbitrary[Map[K, V]].map(s => SortedMap.empty[K, V](implicitly[Order[K]].toOrdering) ++ s))

// Copied from cats-laws.
implicit def cogenSortedMap[K: Order: Cogen, V: Cogen]: Cogen[SortedMap[K, V]] = {
implicit val orderingK = Order[K].toOrdering

implicitly[Cogen[Map[K, V]]].contramap(_.toMap)
}

// Copied from cats-laws.
implicit def arbitrarySortedSet[A: Arbitrary: Order]: Arbitrary[SortedSet[A]] =
Arbitrary(arbitrary[Set[A]].map(s => SortedSet.empty[A](implicitly[Order[A]].toOrdering) ++ s))

// Copied from cats-laws.
implicit def cogenSortedSet[A: Order: Cogen]: Cogen[SortedSet[A]] = {
implicit val orderingA = Order[A].toOrdering

implicitly[Cogen[Set[A]]].contramap(_.toSet)
}

// this instance is not available in ScalaCheck 1.13.2.
// remove this once a newer version is available.
implicit val cogenBigInt: Cogen[BigInt] =
Expand Down Expand Up @@ -127,6 +149,7 @@ class Tests extends AnyFunSuiteLike with Discipline with ScalaVersionSpecificTes
// needed for Cogen[Map[...]]
implicit val ohe: Ordering[HasEq[Int]] = Ordering.by[HasEq[Int], Int](_.a)
checkAll("Eq[Map[String, HasEq[Int]]]", EqTests[Map[String, HasEq[Int]]].eqv)
checkAll("Eq[SortedMap[String, HasEq[Int]]]", EqTests[SortedMap[String, HasEq[Int]]].eqv)
}

checkAll("Eq[List[HasEq[Int]]]", EqTests[List[HasEq[Int]]].eqv)
Expand Down Expand Up @@ -172,6 +195,7 @@ class Tests extends AnyFunSuiteLike with Discipline with ScalaVersionSpecificTes
checkAll("Order[Vector[Int]]", OrderTests[Vector[Int]].order)
checkAll("Order[Stream[Int]]", OrderTests[Stream[Int]].order)
checkAll("Order[Queue[Int]]", OrderTests[Queue[Int]].order)
checkAll("Order[SortedSet[String]", OrderTests[SortedSet[String]].order)
checkAll("fromOrdering[Int]", OrderTests(Order.fromOrdering[Int]).order)
checkAll("Order.reverse(Order[Int])", OrderTests(Order.reverse(Order[Int])).order)
checkAll("Order.reverse(Order.reverse(Order[Int]))", OrderTests(Order.reverse(Order.reverse(Order[Int]))).order)
Expand Down Expand Up @@ -217,16 +241,24 @@ class Tests extends AnyFunSuiteLike with Discipline with ScalaVersionSpecificTes
checkAll("Monoid[List[String]]", SerializableTests.serializable(Monoid[List[String]]))
checkAll("Monoid[Map[String, String]]", MonoidTests[Map[String, String]].monoid)
checkAll("Monoid[Map[String, String]]", SerializableTests.serializable(Monoid[Map[String, String]]))
checkAll("Monoid[SortedMap[String, String]]", MonoidTests[SortedMap[String, String]].monoid)
checkAll("Monoid[SortedMap[String, String]]", SerializableTests.serializable(Monoid[SortedMap[String, String]]))
checkAll("Monoid[Queue[Int]]", MonoidTests[Queue[Int]].monoid)
checkAll("Monoid[Queue[Int]]", SerializableTests.serializable(Monoid[Queue[Int]]))

checkAll("CommutativeMonoid[Map[String, Int]]", CommutativeMonoidTests[Map[String, Int]].commutativeMonoid)
checkAll("CommutativeMonoid[Map[String, Int]]", SerializableTests.serializable(CommutativeMonoid[Map[String, Int]]))
checkAll("CommutativeMonoid[SortedMap[String, Int]]",
CommutativeMonoidTests[SortedMap[String, Int]].commutativeMonoid)
checkAll("CommutativeMonoid[SortedMap[String, Int]]",
SerializableTests.serializable(CommutativeMonoid[SortedMap[String, Int]]))

checkAll("BoundedSemilattice[BitSet]", BoundedSemilatticeTests[BitSet].boundedSemilattice)
checkAll("BoundedSemilattice[BitSet]", SerializableTests.serializable(BoundedSemilattice[BitSet]))
checkAll("BoundedSemilattice[Set[Int]]", BoundedSemilatticeTests[Set[Int]].boundedSemilattice)
checkAll("BoundedSemilattice[Set[Int]]", SerializableTests.serializable(BoundedSemilattice[Set[Int]]))
checkAll("BoundedSemilattice[SortedSet[Int]]", BoundedSemilatticeTests[SortedSet[Int]].boundedSemilattice)
checkAll("BoundedSemilattice[SortedSet[Int]]", SerializableTests.serializable(BoundedSemilattice[SortedSet[Int]]))

checkAll("CommutativeGroup[Unit]", CommutativeGroupTests[Unit].commutativeGroup)
checkAll("CommutativeGroup[Unit]", SerializableTests.serializable(CommutativeGroup[Unit]))
Expand Down Expand Up @@ -275,6 +307,7 @@ class Tests extends AnyFunSuiteLike with Discipline with ScalaVersionSpecificTes
checkAll("Hash[(Int, String)]", HashTests[(Int, String)].hash)
checkAll("Hash[Either[Int, String]]", HashTests[Either[Int, String]].hash)
checkAll("Hash[Map[Int, String]]", HashTests[Map[Int, String]].hash)
checkAll("Hash[SortedMap[Int, String]]", HashTests[SortedMap[Int, String]].hash)
checkAll("Hash[Queue[Int]", HashTests[Queue[Int]].hash)

{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,5 @@ trait AllInstances
with VectorInstances

private[instances] trait AllInstancesBinCompat0 extends FiniteDurationInstances

private[instances] trait AllInstancesBinCompat1 extends SortedMapInstances with SortedSetInstances
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ trait AllInstances
with VectorInstances

private[instances] trait AllInstancesBinCompat0 extends FiniteDurationInstances

private[instances] trait AllInstancesBinCompat1 extends SortedMapInstances with SortedSetInstances
Loading

0 comments on commit a7373fe

Please sign in to comment.