Created
May 3, 2020 08:54
-
-
Save ghostdogpr/875ed2db65edff6209fed40e9721a882 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.deriving._ | |
import scala.quoted._ | |
import scala.quoted.matching._ | |
import scala.compiletime._ | |
trait Show[T] { | |
def show(x: T): String | |
} | |
object Show { | |
inline def tryShow[T](x: T): String = summonInline[Show[T]].show(x) | |
inline def showElems[Elems <: Tuple, Labels <: Tuple](n: Int)(x: Any): List[String] = | |
inline erasedValue[Elems] match { | |
case _: (elem *: elems1) => | |
inline erasedValue[Labels] match { | |
case _: (label *: labels1) => | |
val formal = constValue[label] | |
val actual = tryShow(productElement[elem](x, n)) | |
s"$formal = $actual" :: showElems[elems1, labels1](n + 1)(x) | |
} | |
case _: Unit => | |
Nil | |
} | |
inline def showCase[T](x: Any, m: Mirror.ProductOf[T]): String = { | |
val label = constValue[m.MirroredLabel] | |
inline m match { | |
case m: Mirror.Singleton => label | |
case _ => showElems[m.MirroredElemTypes, m.MirroredElemLabels](0)(x).mkString(s"$label(", ", ", ")") | |
} | |
} | |
inline def showCases[Alts <: Tuple](n: Int)(x: Any, ord: Int): String = | |
inline erasedValue[Alts] match { | |
case _: (alt *: alts1) => | |
if (ord == n) showCase(x, summonInline[Mirror.ProductOf[`alt`]]) | |
else showCases[alts1](n + 1)(x, ord) | |
case _: Unit => | |
throw new MatchError(x) | |
} | |
inline def derived[T]: Show[T] = | |
summonFrom { | |
case ev: Mirror.Of[T] => | |
inline ev match { | |
case m: Mirror.SumOf[T] => | |
new Show[T] { | |
def show(x: T): String = { | |
val ord = m.ordinal(x) | |
showCases[m.MirroredElemTypes](0)(x, ord) | |
} | |
} | |
case m: Mirror.ProductOf[T] => | |
new Show[T] { | |
def show(x: T): String = { | |
showCase(x, m) | |
} | |
} | |
} | |
} | |
implicit object IntShow extends Show[Int] { | |
def show(x: Int): String = x.toString | |
} | |
implicit object StringShow extends Show[String] { | |
def show(x: String): String = x | |
} | |
// implicit object BooleanShow extends Show[Boolean] { | |
// def show(x: Boolean): String = x.toString | |
// } | |
} | |
@main def showTest() = { | |
import Show._ | |
case class Address(street: String, a: Boolean) | |
case class Person(name: String, address: Address) | |
implicit inline def showGen[T]: Show[T] = Show.derived[T] | |
println(showGen[Address].show(Address("a", true))) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment