Last active
February 8, 2025 08:46
-
-
Save ghostdogpr/6f2ca0939c67765a0657a255ed653765 to your computer and use it in GitHub Desktop.
Sum Type Derivation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.annotation.nowarn | |
import scala.deriving.Mirror | |
trait TC[A] { | |
def show(a: A): Unit | |
} | |
@nowarn | |
inline def gen[A](using m: Mirror.SumOf[A]): TC[A] = { | |
val subTypes = compiletime.summonAll[Tuple.Map[m.MirroredElemTypes, TC]] | |
new TC[A] { | |
def show(a: A): Unit = | |
subTypes(m.ordinal(a)).asInstanceOf[TC[A]].show(a) | |
} | |
} | |
sealed trait Parent | |
case class A() extends Parent | |
object A { | |
given TC[A] = new TC[A] { | |
def show(a: A): Unit = println("a") | |
} | |
} | |
case class B() extends Parent | |
object B { | |
given TC[B] = new TC[B] { | |
def show(a: B): Unit = println("b") | |
} | |
} | |
object C extends Parent { | |
given TC[C.type] = new TC[C.type] { | |
def show(a: C.type): Unit = println("c") | |
} | |
} | |
val tc = gen[Parent] | |
tc.show(A()) | |
tc.show(B()) | |
tc.show(C) |
Thanks for pointing me to using summonAll
instead of recursive inlining - for example, the following will hit "Maximal number of successive inlines (32) exceeded" with scala 3.3.5, but will compile with 3.4.0 and above:
inline def productInstance[T](using p: scala.deriving.Mirror.ProductOf[T]) =
scala.compiletime.summonAll[Tuple.Map[p.MirroredElemTypes, Ordering]]
case class BigCaseClass(
a1: Int, b1: Int, c1: Int, d1: Int, e1: Int, f1: Int, g1: Int, h1: Int, i1: Int, j1: Int,
k1: Int, l1: Int, m1: Int, n1: Int, o1: Int, p1: Int, q1: Int, r1: Int, s1: Int, t1: Int,
u1: Int, v1: Int, w1: Int, x1: Int, y1: Int, z1: Int,
a2: Int, b2: Int, c2: Int, d2: Int, e2: Int, f2: Int, g2: Int, h2: Int, i2: Int, j2: Int,
k2: Int, l2: Int, m2: Int, n2: Int, o2: Int, p2: Int, q2: Int, r2: Int, s2: Int, t2: Int
)
val x = productInstance[BigCaseClass]
Seems like this commit is what changed the behavior.
Since library authors are expected to stay on 3.3.x, it might be worth to actively point this out to any authors of libs that could improve the "max-inlines"-behavior of their lib. (Good thing is: the new behavior will apply if a lib using summonAll
that is compiled with 3.3.x is used from a project using 3.4.0 or higher.)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Instead of:
you could write:
The
.stripSuffix("$")
is code I've seen in Spark codebaseSee https://github.com/search?q=repo%3Aapache%2Fspark%20stripSuffix(%22%24%22)&type=code
Not sure it's any better. Maybe a bit more explicit than
.dropRight(1)
but it's pretty similar and maybe not worth it.