From be4bc431d9a96e06a36bcd40773e175e4f04dce9 Mon Sep 17 00:00:00 2001 From: Georgi Krastev Date: Sat, 27 Apr 2024 21:19:57 +0200 Subject: [PATCH] Accommodate user-defined mirrors by adding a given fromMirror --- .../scala/shapeless3/deriving/kinds.scala | 25 +++++++---- .../scala/shapeless3/deriving/deriving.scala | 42 +++++++++++++++++-- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/modules/deriving/src/main/scala/shapeless3/deriving/kinds.scala b/modules/deriving/src/main/scala/shapeless3/deriving/kinds.scala index 803538a..bf5a0cd 100644 --- a/modules/deriving/src/main/scala/shapeless3/deriving/kinds.scala +++ b/modules/deriving/src/main/scala/shapeless3/deriving/kinds.scala @@ -22,20 +22,21 @@ import scala.Tuple.Union import scala.compiletime.* import scala.compiletime.ops.int.S import scala.deriving.* -import scala.util.NotGiven object K0: - type Kind[C, O] = C { - type Kind = K0.type + infix type of[M <: Mirror, O] = M { type MirroredType = O type MirroredMonoType = O type MirroredElemTypes <: Tuple } + type Kind[M <: Mirror, O] = (M of O) { type Kind = K0.type } type Generic[O] = Kind[Mirror, O] type ProductGeneric[O] = Kind[Mirror.Product, O] type CoproductGeneric[O] = Kind[Mirror.Sum, O] + given fromMirror[M <: Mirror, O](using m: M of O): Kind[m.type, O] = m.asInstanceOf + def Generic[O](using gen: Generic[O]): gen.type = gen def ProductGeneric[O](using gen: ProductGeneric[O]): gen.type = gen def CoproductGeneric[O](using gen: CoproductGeneric[O]): gen.type = gen @@ -178,17 +179,19 @@ object K0: ErasedCoproductInstances[K0.type, F[T], LiftP[F, gen.MirroredElemTypes]](gen): CoproductInstances[F, T] object K1: - type Kind[C, O[_]] = C { - type Kind = K1.type + infix type of[M <: Mirror, O[_]] = M { type MirroredType[X] = O[X] type MirroredMonoType = O[Any] type MirroredElemTypes[_] <: Tuple } + type Kind[M <: Mirror, O[_]] = (M of O) { type Kind = K1.type } type Generic[O[_]] = Kind[Mirror, O] type ProductGeneric[O[_]] = Kind[Mirror.Product, O] type CoproductGeneric[O[_]] = Kind[Mirror.Sum, O] + given fromMirror[M <: Mirror, O[_]](using m: M of O): Kind[m.type, O] = m.asInstanceOf + def Generic[O[_]](using gen: Generic[O]): gen.type = gen def ProductGeneric[O[_]](using gen: ProductGeneric[O]): gen.type = gen def CoproductGeneric[O[_]](using gen: CoproductGeneric[O]): gen.type = gen @@ -327,17 +330,19 @@ object K1: ErasedCoproductInstances[K1.type, F[T], LiftP[F, gen.MirroredElemTypes]](gen) object K11: - type Kind[C, O[_[_]]] = C { - type Kind = K11.type + infix type of[M <: Mirror, O[_[_]]] = M { type MirroredType[X[_]] = O[X] type MirroredMonoType = O[[_] =>> Any] type MirroredElemTypes[_[_]] <: Tuple } + type Kind[M <: Mirror, O[_[_]]] = (M of O) { type Kind = K11.type } type Generic[O[_[_]]] = Kind[Mirror, O] type ProductGeneric[O[_[_]]] = Kind[Mirror.Product, O] type CoproductGeneric[O[_[_]]] = Kind[Mirror.Sum, O] + given fromMirror[M <: Mirror, O[_[_]]](using m: M of O): Kind[m.type, O] = m.asInstanceOf + def Generic[O[_[_]]](using gen: Generic[O]): gen.type = gen def ProductGeneric[O[_[_]]](using gen: ProductGeneric[O]): gen.type = gen def CoproductGeneric[O[_[_]]](using gen: CoproductGeneric[O]): gen.type = gen @@ -483,17 +488,19 @@ object K11: ErasedCoproductInstances[K11.type, F[T], LiftP[F, gen.MirroredElemTypes]](gen) object K2: - type Kind[C, O[_, _]] = C { - type Kind = K2.type + infix type of[M <: Mirror, O[_, _]] = M { type MirroredType[X, Y] = O[X, Y] type MirroredMonoType = O[Any, Any] type MirroredElemTypes[_, _] <: Tuple } + type Kind[M <: Mirror, O[_, _]] = (M of O) { type Kind = K2.type } type Generic[O[_, _]] = Kind[Mirror, O] type ProductGeneric[O[_, _]] = Kind[Mirror.Product, O] type CoproductGeneric[O[_, _]] = Kind[Mirror.Sum, O] + given fromMirror[M <: Mirror, O[_, _]](using m: M of O): Kind[m.type, O] = m.asInstanceOf + def Generic[O[_, _]](using gen: Generic[O]): gen.type = gen def ProductGeneric[O[_, _]](using gen: ProductGeneric[O]): gen.type = gen def CoproductGeneric[O[_, _]](using gen: CoproductGeneric[O]): gen.type = gen diff --git a/modules/deriving/src/test/scala/shapeless3/deriving/deriving.scala b/modules/deriving/src/test/scala/shapeless3/deriving/deriving.scala index efe0044..dd2bc3f 100644 --- a/modules/deriving/src/test/scala/shapeless3/deriving/deriving.scala +++ b/modules/deriving/src/test/scala/shapeless3/deriving/deriving.scala @@ -21,11 +21,11 @@ import org.junit.Test import scala.annotation.tailrec import scala.compiletime.constValueTuple - import cats.Eval - import adts.* -import OptE.{SmE, NnE} +import OptE.{NnE, SmE} + +import scala.deriving.Mirror // Tests @@ -393,3 +393,39 @@ class DerivationTests: assertEquals(Right(ISB(42, "foo", true)), parser.parseShort("s=foo,i=42,b=true,hidden=?")) assertEquals(Left("Missing field 's';"), parser.parseShort("i=42,b=kinda")) assertEquals(Left("Invalid field 'broken';"), parser.parseShort("i=42,broken,?")) + + @Test + def userDefinedMirrors(): Unit = + def show[A](using + m: Mirror.ProductOf[A] { + type MirroredLabel = "ISB" + type MirroredElemLabels = ("i", "s", "b") + type MirroredElemTypes = (Int, String, Boolean) + } + ): Unit = + assertEquals(m, K0.Generic[A]) + assertNotNull(Show[A]) + + def bifunctor[F[_, _]](using + m: Mirror.Sum { + type MirroredType[A, B] = F[A, B] + type MirroredMonoType = F[Any, Any] + type MirroredElemTypes[A, B] = ((A, B), Unit) + } + ): Unit = + assertEquals(m, K2.CoproductGeneric[F]) + assertNotNull(Bifunctor[F]) + + def functorK[Alg[_[_]]](using + m: Mirror.Product { + type MirroredType[F[_]] = Alg[F] + type MirroredMonoType = Alg[[_] =>> Any] + type MirroredElemTypes[F[_]] = (F[String], F[Int]) + } + ): Unit = + assertEquals(m, K11.Generic[Alg]) + assertNotNull(FunctorK[Alg]) + + show[ISB] + bifunctor[ListF] + functorK[Order]