Skip to content

Commit

Permalink
Accommodate user-defined mirrors by adding a given fromMirror
Browse files Browse the repository at this point in the history
  • Loading branch information
joroKr21 committed Apr 27, 2024
1 parent 2e608ee commit 4a73376
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 12 deletions.
25 changes: 16 additions & 9 deletions modules/deriving/src/main/scala/shapeless3/deriving/kinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
43 changes: 40 additions & 3 deletions modules/deriving/src/test/scala/shapeless3/deriving/deriving.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -393,3 +393,40 @@ 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]
end userDefinedMirrors

0 comments on commit 4a73376

Please sign in to comment.