From f1e547244587140516645e868a4e81491b5e6fe5 Mon Sep 17 00:00:00 2001 From: Ben Plommer Date: Wed, 2 Jun 2021 09:12:25 +0100 Subject: [PATCH 1/5] use SummonFrom to prioritize DerivedEmpty instances --- .../src/main/scala-3/cats/derived/empty.scala | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/core/src/main/scala-3/cats/derived/empty.scala b/core/src/main/scala-3/cats/derived/empty.scala index ff192a8c..03217a30 100644 --- a/core/src/main/scala-3/cats/derived/empty.scala +++ b/core/src/main/scala-3/cats/derived/empty.scala @@ -2,6 +2,7 @@ package cats.derived import alleycats.Empty import shapeless3.deriving.K0 +import scala.compiletime.summonFrom object empty extends EmptyDerivation @@ -9,22 +10,26 @@ trait DerivedEmpty[A] extends Empty[A]: protected def emptyValue(): A lazy val empty: A = emptyValue() -object DerivedEmpty extends DerivedEmptyLowPriority: - given delegated[A](using A: => Empty[A]): DerivedEmpty[A] = +object DerivedEmpty: + inline given [A]: DerivedEmpty[A] = summonFrom { + case given Empty[A] => delegated + case given K0.Generic[A] => derived + } + + private def delegated[A](using A: => Empty[A]): DerivedEmpty[A] = () => A.empty + inline def derived[A](using gen: K0.Generic[A]): DerivedEmpty[A] = + inline gen match + case given K0.ProductGeneric[A] => DerivedEmpty.product + case given K0.CoproductGeneric[A] => DerivedEmpty.coproduct + def product[A](using inst: K0.ProductInstances[DerivedEmpty, A]): DerivedEmpty[A] = () => inst.construct([A] => (A: DerivedEmpty[A]) => A.empty) inline def coproduct[A](using gen: K0.CoproductGeneric[A]): DerivedEmpty[A] = K0.summonFirst[DerivedEmpty, gen.MirroredElemTypes, A] -private[derived] sealed abstract class DerivedEmptyLowPriority: - inline given derived[A](using gen: K0.Generic[A]): DerivedEmpty[A] = - inline gen match - case given K0.ProductGeneric[A] => DerivedEmpty.product - case given K0.CoproductGeneric[A] => DerivedEmpty.coproduct - trait EmptyDerivation: extension (E: Empty.type) def derived[A](using instance: DerivedEmpty[A]): Empty[A] = instance From 422231566a5209cd143f582cfc532253317a5719 Mon Sep 17 00:00:00 2001 From: Ben Plommer Date: Wed, 2 Jun 2021 09:14:11 +0100 Subject: [PATCH 2/5] make delegated non private --- core/src/main/scala-3/cats/derived/empty.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala-3/cats/derived/empty.scala b/core/src/main/scala-3/cats/derived/empty.scala index 03217a30..76b5c849 100644 --- a/core/src/main/scala-3/cats/derived/empty.scala +++ b/core/src/main/scala-3/cats/derived/empty.scala @@ -16,7 +16,7 @@ object DerivedEmpty: case given K0.Generic[A] => derived } - private def delegated[A](using A: => Empty[A]): DerivedEmpty[A] = + def delegated[A](using A: => Empty[A]): DerivedEmpty[A] = () => A.empty inline def derived[A](using gen: K0.Generic[A]): DerivedEmpty[A] = From d4e5b648a21ea5b7662a3b7c08d3f66cb5eb7480 Mon Sep 17 00:00:00 2001 From: Ben Plommer Date: Wed, 2 Jun 2021 10:49:09 +0100 Subject: [PATCH 3/5] simplify DerivedEmpty further --- core/src/main/scala-3/cats/derived/empty.scala | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/core/src/main/scala-3/cats/derived/empty.scala b/core/src/main/scala-3/cats/derived/empty.scala index 76b5c849..0260d426 100644 --- a/core/src/main/scala-3/cats/derived/empty.scala +++ b/core/src/main/scala-3/cats/derived/empty.scala @@ -13,17 +13,13 @@ trait DerivedEmpty[A] extends Empty[A]: object DerivedEmpty: inline given [A]: DerivedEmpty[A] = summonFrom { case given Empty[A] => delegated - case given K0.Generic[A] => derived + case given K0.ProductInstances[DerivedEmpty, A] => product + case given K0.CoproductGeneric[A] => coproduct } def delegated[A](using A: => Empty[A]): DerivedEmpty[A] = () => A.empty - inline def derived[A](using gen: K0.Generic[A]): DerivedEmpty[A] = - inline gen match - case given K0.ProductGeneric[A] => DerivedEmpty.product - case given K0.CoproductGeneric[A] => DerivedEmpty.coproduct - def product[A](using inst: K0.ProductInstances[DerivedEmpty, A]): DerivedEmpty[A] = () => inst.construct([A] => (A: DerivedEmpty[A]) => A.empty) From 07abf513d911cc1c87236b3ca053910ed6856c28 Mon Sep 17 00:00:00 2001 From: Ben Plommer Date: Wed, 2 Jun 2021 13:41:01 +0100 Subject: [PATCH 4/5] fix loop --- .../src/main/scala-3/cats/derived/empty.scala | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/core/src/main/scala-3/cats/derived/empty.scala b/core/src/main/scala-3/cats/derived/empty.scala index 0260d426..7dc31a0c 100644 --- a/core/src/main/scala-3/cats/derived/empty.scala +++ b/core/src/main/scala-3/cats/derived/empty.scala @@ -3,6 +3,7 @@ package cats.derived import alleycats.Empty import shapeless3.deriving.K0 import scala.compiletime.summonFrom +import scala.util.NotGiven object empty extends EmptyDerivation @@ -10,22 +11,47 @@ trait DerivedEmpty[A] extends Empty[A]: protected def emptyValue(): A lazy val empty: A = emptyValue() +enum EmptyOrDerived[A]: + case L(empty: Empty[A]) + case R(derived: DerivedEmpty[A]) + +object EmptyOrDerived: + inline given [A]: EmptyOrDerived[A] = summonFrom { + case e: Empty[A] => L(e) + case d: DerivedEmpty[A] => R(d) + } + object DerivedEmpty: inline given [A]: DerivedEmpty[A] = summonFrom { - case given Empty[A] => delegated - case given K0.ProductInstances[DerivedEmpty, A] => product + case given K0.ProductInstances[EmptyOrDerived, A] => product case given K0.CoproductGeneric[A] => coproduct } - - def delegated[A](using A: => Empty[A]): DerivedEmpty[A] = - () => A.empty - def product[A](using inst: K0.ProductInstances[DerivedEmpty, A]): DerivedEmpty[A] = - () => inst.construct([A] => (A: DerivedEmpty[A]) => A.empty) + def product[A](using inst: K0.ProductInstances[EmptyOrDerived, A]): DerivedEmpty[A] = + () => inst.construct([A] => (A: EmptyOrDerived[A]) => + A match { + case EmptyOrDerived.L(e) => e.empty + case EmptyOrDerived.R(d) => d.empty + }) inline def coproduct[A](using gen: K0.CoproductGeneric[A]): DerivedEmpty[A] = - K0.summonFirst[DerivedEmpty, gen.MirroredElemTypes, A] + K0.summonFirst[EmptyOrDerived, gen.MirroredElemTypes, A] match { + case EmptyOrDerived.L(e) => () => e.empty + case EmptyOrDerived.R(d) => d + } trait EmptyDerivation: extension (E: Empty.type) - def derived[A](using instance: DerivedEmpty[A]): Empty[A] = instance + def derived[A](using instance: DerivedEmpty[A]): Empty[A] = + Empty(instance.empty) + + +import empty.derived + +case class Foo(i: Int, b: IntTree) derives Empty +enum IntTree: + case Leaf + case Node(left: IntTree, value: Int, right: IntTree) + +@main def run = + println(Empty[Foo].empty) From e896ac1117f2238656efeecbd7209129faaf2507 Mon Sep 17 00:00:00 2001 From: Ben Plommer Date: Wed, 2 Jun 2021 13:45:28 +0100 Subject: [PATCH 5/5] Remove unused import --- core/src/main/scala-3/cats/derived/empty.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/scala-3/cats/derived/empty.scala b/core/src/main/scala-3/cats/derived/empty.scala index e174076f..8fecdd1b 100644 --- a/core/src/main/scala-3/cats/derived/empty.scala +++ b/core/src/main/scala-3/cats/derived/empty.scala @@ -3,7 +3,6 @@ package cats.derived import alleycats.Empty import shapeless3.deriving.K0 import scala.compiletime.summonFrom -import scala.util.NotGiven object empty extends EmptyDerivation