From 67a012cdcc637809d7ec5f89cc31bdd82dfcc90e Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Fri, 27 Aug 2021 20:08:42 +0300 Subject: [PATCH 1/2] [WIP] Port TraverseSuite to Scala 3 --- .../scala-3/cats/derived/TraverseSuite.scala | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 core/src/test/scala-3/cats/derived/TraverseSuite.scala diff --git a/core/src/test/scala-3/cats/derived/TraverseSuite.scala b/core/src/test/scala-3/cats/derived/TraverseSuite.scala new file mode 100644 index 00000000..2c3c7c36 --- /dev/null +++ b/core/src/test/scala-3/cats/derived/TraverseSuite.scala @@ -0,0 +1,65 @@ +package cats +package derived + +import cats.laws.discipline.{SerializableTests, TraverseTests} + +class TraverseSuite extends KittensSuite { + import TestDefns.* + import TraverseSuite.* + + def testTraverse(context: String)(implicit + iList: Traverse[IList], + tree: Traverse[Tree], + genericAdt: Traverse[GenericAdt], + optList: Traverse[OptList], + listSnoc: Traverse[ListSnoc], + andChar: Traverse[AndChar], + interleaved: Traverse[Interleaved] + ): Unit = { + checkAll(s"$context.Traverse[IList]", TraverseTests[IList].traverse[Int, Double, String, Long, Option, Option]) + checkAll(s"$context.Traverse[Tree]", TraverseTests[Tree].traverse[Int, Double, String, Long, Option, Option]) + checkAll( + s"$context.Traverse[GenericAdt]", + TraverseTests[GenericAdt].traverse[Int, Double, String, Long, Option, Option] + ) + checkAll(s"$context.Traverse[OptList]", TraverseTests[OptList].traverse[Int, Double, String, Long, Option, Option]) + checkAll( + s"$context.Traverse[ListSnoc]", + TraverseTests[ListSnoc].traverse[Int, Double, String, Long, Option, Option] + ) + checkAll(s"$context.Traverse[AndChar]", TraverseTests[AndChar].traverse[Int, Double, String, Long, Option, Option]) + checkAll( + s"$context.Traverse[Interleaved]", + TraverseTests[Interleaved].traverse[Int, Double, String, Long, Option, Option] + ) + checkAll(s"$context.Traverse is Serializable", SerializableTests.serializable(Traverse[Tree])) + } + + { + import auto.traverse.given + testTraverse("auto") + } + + { + import semiInstances._ + testTraverse("semiauto") + } +} + +object TraverseSuite { + import TestDefns._ + + type OptList[A] = Option[List[A]] + type ListSnoc[A] = List[Snoc[A]] + type AndChar[A] = (A, Char) + + object semiInstances { + implicit val iList: Traverse[IList] = semiauto.traverse + implicit val tree: Traverse[Tree] = semiauto.traverse + implicit val genericAdt: Traverse[GenericAdt] = semiauto.traverse + implicit val optList: Traverse[OptList] = semiauto.traverse + implicit val listSnoc: Traverse[ListSnoc] = semiauto.traverse + implicit val andChar: Traverse[AndChar] = semiauto.traverse + implicit val interleaved: Traverse[Interleaved] = semiauto.traverse + } +} From 1f623d930a39b847603e79d68eb93ec1fd830ee6 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sun, 26 Sep 2021 19:32:01 +0200 Subject: [PATCH 2/2] Update shapeless and fix TraverseSuite --- build.sbt | 2 +- .../scala-3/cats/derived/TraverseSuite.scala | 81 ++++++++++--------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/build.sbt b/build.sbt index bd88aa0a..1e45d216 100644 --- a/build.sbt +++ b/build.sbt @@ -15,7 +15,7 @@ val catsVersion = "2.6.1" val disciplineMunitVersion = "1.0.9" val kindProjectorVersion = "0.13.0" val shapeless2Version = "2.3.7" -val shapeless3Version = "3.0.2" +val shapeless3Version = "3.0.3" lazy val commonSettings = Seq( scalacOptions := Seq( diff --git a/core/src/test/scala-3/cats/derived/TraverseSuite.scala b/core/src/test/scala-3/cats/derived/TraverseSuite.scala index 2c3c7c36..bea234ce 100644 --- a/core/src/test/scala-3/cats/derived/TraverseSuite.scala +++ b/core/src/test/scala-3/cats/derived/TraverseSuite.scala @@ -1,65 +1,70 @@ -package cats -package derived +package cats.derived +import cats.{Eq, Traverse} import cats.laws.discipline.{SerializableTests, TraverseTests} +import org.scalacheck.Arbitrary -class TraverseSuite extends KittensSuite { +import scala.compiletime.* + +class TraverseSuite extends KittensSuite: import TestDefns.* import TraverseSuite.* - def testTraverse(context: String)(implicit - iList: Traverse[IList], - tree: Traverse[Tree], - genericAdt: Traverse[GenericAdt], - optList: Traverse[OptList], - listSnoc: Traverse[ListSnoc], - andChar: Traverse[AndChar], - interleaved: Traverse[Interleaved] - ): Unit = { - checkAll(s"$context.Traverse[IList]", TraverseTests[IList].traverse[Int, Double, String, Long, Option, Option]) - checkAll(s"$context.Traverse[Tree]", TraverseTests[Tree].traverse[Int, Double, String, Long, Option, Option]) + inline def traverseTests[F[_]]: TraverseTests[F] = + TraverseTests[F](summonInline) + + inline def testTraverse(inline context: String): Unit = + checkAll(s"$context.Traverse[IList]", traverseTests[IList].traverse[Int, Double, String, Long, Option, Option]) + checkAll(s"$context.Traverse[Tree]", traverseTests[Tree].traverse[Int, Double, String, Long, Option, Option]) checkAll( s"$context.Traverse[GenericAdt]", - TraverseTests[GenericAdt].traverse[Int, Double, String, Long, Option, Option] + traverseTests[GenericAdt].traverse[Int, Double, String, Long, Option, Option] ) - checkAll(s"$context.Traverse[OptList]", TraverseTests[OptList].traverse[Int, Double, String, Long, Option, Option]) + checkAll(s"$context.Traverse[OptList]", traverseTests[OptList].traverse[Int, Double, String, Long, Option, Option]) checkAll( s"$context.Traverse[ListSnoc]", - TraverseTests[ListSnoc].traverse[Int, Double, String, Long, Option, Option] + traverseTests[ListSnoc].traverse[Int, Double, String, Long, Option, Option] ) - checkAll(s"$context.Traverse[AndChar]", TraverseTests[AndChar].traverse[Int, Double, String, Long, Option, Option]) + checkAll(s"$context.Traverse[AndChar]", traverseTests[AndChar].traverse[Int, Double, String, Long, Option, Option]) checkAll( s"$context.Traverse[Interleaved]", - TraverseTests[Interleaved].traverse[Int, Double, String, Long, Option, Option] + traverseTests[Interleaved].traverse[Int, Double, String, Long, Option, Option] ) - checkAll(s"$context.Traverse is Serializable", SerializableTests.serializable(Traverse[Tree])) - } + checkAll(s"$context.Traverse is Serializable", SerializableTests.serializable(summonInline[Traverse[Tree]])) - { + locally { import auto.traverse.given testTraverse("auto") } - { - import semiInstances._ + locally { + import semiInstances.given testTraverse("semiauto") } -} -object TraverseSuite { - import TestDefns._ +end TraverseSuite + +object TraverseSuite: + import TestDefns.* type OptList[A] = Option[List[A]] type ListSnoc[A] = List[Snoc[A]] - type AndChar[A] = (A, Char) - object semiInstances { - implicit val iList: Traverse[IList] = semiauto.traverse - implicit val tree: Traverse[Tree] = semiauto.traverse - implicit val genericAdt: Traverse[GenericAdt] = semiauto.traverse - implicit val optList: Traverse[OptList] = semiauto.traverse - implicit val listSnoc: Traverse[ListSnoc] = semiauto.traverse - implicit val andChar: Traverse[AndChar] = semiauto.traverse - implicit val interleaved: Traverse[Interleaved] = semiauto.traverse - } -} + // FIXME: Doesn't work if we define `ListAndNel` as a type alias + case class AndChar[A](value: A, letter: Char) + object AndChar: + given [A: Eq]: Eq[AndChar[A]] = + Eq.by(ac => (ac.value, ac.letter)) + given [A: Arbitrary]: Arbitrary[AndChar[A]] = + Arbitrary(Arbitrary.arbitrary[(A, Char)].map(apply[A].tupled)) + + object semiInstances: + given Traverse[IList] = semiauto.traverse + given Traverse[Tree] = semiauto.traverse + given Traverse[GenericAdt] = semiauto.traverse + given Traverse[OptList] = semiauto.traverse + given Traverse[ListSnoc] = semiauto.traverse + given Traverse[AndChar] = semiauto.traverse + given Traverse[Interleaved] = semiauto.traverse + +end TraverseSuite