-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Mirror.Sum for union types #21
Comments
Thanks for the report ... shapeless 3 doesn't currently support union types. In principle support could be added. We would have to support the creation of |
Thanks! |
I've been experimenting with Union types recently. Perhaps some samples can be reused in shapeless-3:
Actually, it would be nice to have this logic as a part of the Scala compiler (perhaps as a part of the Mirror). |
@iRevive nice! Do you think that can be generalized for kinds other than Bear in mind that If you were interested in exploring that space I'd be super keen to see that in shapeless 3. |
@milessabin thank you for the feedback. I experimented a bit with the Mirror. The example is available here https://scastie.scala-lang.org/k3VLtxUTTie18YodrQKtJw. Mirror.SumOfIn the example below the compiler loses type information of the given unionMirror: Mirror.SumOf[Int | String | Long] = new Mirror.Sum {
type MirroredType = Int | String | Long
type MirroredMonoType = Int | String | Long
type MirroredLabel = "Int | String | Long"
type MirroredElemTypes = Int *: String *: Long *: EmptyTuple
type MirroredElemLabels = Tuple3["Int", "String", "Long"]
def ordinal(x: MirroredMonoType): Int = x match {
case _: Int => 0
case _: String => 1
case _: Long => 2
}
}
summon[Show[Int | String | Long]].show("string-value") // does not compile
// Error:
// cannot reduce inline match with
// scrutinee: scala.compiletime.erasedValue[Playground.unionMirror.MirroredElemTypes] : Playground.unionMirror.MirroredElemTypes
// patterns : case _:EmptyTuple
// case _:*:[t @ _, ts @ _] This is how the compiler resolves the Alias for Mirror.Sum with full type infoWhen type MirrorUnion[TPE, MET, MEL] = Mirror.Sum {
type MirroredType = TPE
type MirroredMonoType = TPE
type MirroredElemTypes = MET
type MirroredElemLabels = MEL
}
given unionMirror: MirrorUnion[Int | String | Long, Int *: String *: Long *: EmptyTuple, ("Int", "String", "Long")] =
new Mirror.Sum {
//body the same as above
}
summon[Show[Int | String | Long]].show("string-value") // compiles Next stepsI assume it's expected behavior, since type SumOf[T] = Mirror.Sum { type MirroredType = T; type MirroredMonoType = T; type MirroredElemTypes <: Tuple } Currently, I do not understand how the macro can be defined, since the result type should be known. But both I tried the following trick, but the compiler does not like it: object UnionMirror {
// does not compile with the following error:
// access to parameter u from wrong staging level:
// - the definition is at level 0,
// - but the access is at level -1.
inline given derived[A](using u: UnionInfo[A]): u.Mirror = ${ deriveImpl[A] }
def deriveImpl[A: Type](using quotes: Quotes, u: UnionInfo[A]): Expr[u.Mirror] = {
???
}
trait UnionInfo[A] {
type MirroredElemTypes
type MirroredElemLabels
type Mirror = Mirror.Sum {
type MirroredType = A
type MirroredMonoType = A
type MirroredElemTypes = self.MirroredElemTypes
type MirroredElemLabels = self.MirroredElemLabels
}
}
object UnionInfo {
inline given derived[A]: UnionInfo[A] = ...
}
} |
The problem with your manual |
The text was updated successfully, but these errors were encountered: