From e1c9b2c7f2a2904838dad34ba65a3ecc0f189b4e Mon Sep 17 00:00:00 2001 From: Thomas Dufour Date: Sat, 16 Mar 2024 12:30:04 +0100 Subject: [PATCH] fix ambiguous implicit ContravariantShow for SortedSet and SortedMap --- core/src/main/scala/cats/Show.scala | 7 ++-- .../src/test/scala/cats/tests/ShowSuite.scala | 38 +++++++++++++++++-- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/core/src/main/scala/cats/Show.scala b/core/src/main/scala/cats/Show.scala index 881f407a48..dba5f4f4e0 100644 --- a/core/src/main/scala/cats/Show.scala +++ b/core/src/main/scala/cats/Show.scala @@ -107,9 +107,6 @@ object Show extends ScalaVersionSpecificShowInstances with ShowInstances { implicit def catsShowForQueue[A: Show]: Show[Queue[A]] = cats.instances.queue.catsStdShowForQueue[A] implicit def catsShowForEither[A: Show, B: Show]: Show[Either[A, B]] = cats.instances.either.catsStdShowForEither[A, B] - implicit def catsShowForSet[A: Show]: Show[Set[A]] = cats.instances.set.catsStdShowForSet[A] - implicit def catsShowForMap[K: Show, V: Show]: Show[Map[K, V]] = cats.instances.map.catsStdShowForMap[K, V] - implicit def catsShowForSortedSet[A: Show]: Show[SortedSet[A]] = cats.instances.sortedSet.catsStdShowForSortedSet[A] implicit def catsShowForSortedMap[K: Show, V: Show]: Show[SortedMap[K, V]] = cats.instances.sortedMap.catsStdShowForSortedMap[K, V] @@ -120,8 +117,12 @@ object Show extends ScalaVersionSpecificShowInstances with ShowInstances { private[cats] trait ShowInstances extends cats.instances.NTupleShowInstances with ShowInstances0 { implicit def catsShowForFiniteDuration: Show[FiniteDuration] = cats.instances.finiteDuration.catsStdShowForFiniteDurationUnambiguous + + implicit def catsShowForSortedSet[A: Show]: Show[SortedSet[A]] = cats.instances.sortedSet.catsStdShowForSortedSet[A] } private[cats] trait ShowInstances0 { implicit def catsShowForSeq[A: Show]: Show[Seq[A]] = cats.instances.seq.catsStdShowForSeq[A] + implicit def catsShowForMap[K: Show, V: Show]: Show[Map[K, V]] = cats.instances.map.catsStdShowForMap[K, V] + implicit def catsShowForSet[A: Show]: Show[Set[A]] = cats.instances.set.catsStdShowForSet[A] } diff --git a/tests/shared/src/test/scala/cats/tests/ShowSuite.scala b/tests/shared/src/test/scala/cats/tests/ShowSuite.scala index e449a95613..94f22c7bc0 100644 --- a/tests/shared/src/test/scala/cats/tests/ShowSuite.scala +++ b/tests/shared/src/test/scala/cats/tests/ShowSuite.scala @@ -24,13 +24,15 @@ package cats.tests import cats.{Contravariant, Show} import cats.Show.ContravariantShow import cats.kernel.Order -import cats.syntax.show._ +import cats.syntax.show.* import cats.laws.discipline.{ContravariantTests, DeferTests, MiniInt, SerializableTests} -import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ - +import cats.laws.discipline.arbitrary.* +import cats.laws.discipline.eq.* import java.util.concurrent.TimeUnit +import scala.collection.immutable.BitSet import scala.collection.immutable.Seq +import scala.collection.immutable.SortedMap +import scala.collection.immutable.SortedSet import scala.concurrent.duration.{Duration, FiniteDuration} class ShowSuite extends CatsSuite { @@ -83,6 +85,34 @@ class ShowSuite extends CatsSuite { assertEquals(show"${goodmornings.toList}", "List(guten Tag, good morning, bonjour)") assertEquals(show"${goodmornings.toVector}", "Vector(guten Tag, good morning, bonjour)") } + + test("show interpolation with Set subtypes isn't ambiguous") { + implicitly[ContravariantShow[Set[Int]]] + implicitly[ContravariantShow[SortedSet[Int]]] + implicitly[ContravariantShow[BitSet]] + + val numbers: Set[Int] = Set(4, 2, 1, 3) + // relies on the implementation of Set for <= 4 elements, maybe replace the rhs with numbers.mkString(...)? + assertEquals(show"$numbers", "Set(4, 2, 1, 3)") + + val numbersSorted: SortedSet[Int] = SortedSet(4, 2, 1, 3) + assertEquals(show"$numbersSorted", "SortedSet(1, 2, 3, 4)") + + val numbersBitSet: BitSet = BitSet(4, 2, 1, 3) + assertEquals(show"$numbersBitSet", "BitSet(1, 2, 3, 4)") + } + + test("show interpolation with Map subtypes isn't ambiguous") { + implicitly[ContravariantShow[Map[Int, String]]] + implicitly[ContravariantShow[SortedMap[Int, String]]] + + val map: Map[Int, String] = Map(3 -> "three", 1 -> "one", 4 -> "four", 2 -> "two") + // same thing as with Set, relies on an implementation detail of Map + assertEquals(show"$map", "Map(3 -> three, 1 -> one, 4 -> four, 2 -> two)") + + val mapSorted: SortedMap[Int, String] = SortedMap(3 -> "three", 1 -> "one", 4 -> "four", 2 -> "two") + assertEquals(show"$mapSorted", "SortedMap(1 -> one, 2 -> two, 3 -> three, 4 -> four)") + } } final class ShowSuite2 extends munit.FunSuite {