Created
May 21, 2021 17:52
-
-
Save kubukoz/9c40a24acfde0c1ec60b7108473eb26f to your computer and use it in GitHub Desktop.
Deriving a nice Show in scala 3
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.deriving.* | |
import scala.compiletime.* | |
trait Show[T]: | |
extension (t: T) def show: String | |
given Show[String] = s => s | |
given Show[Int] = _.toString | |
object Show: | |
private inline def instances[T <: Tuple]: List[Show[Any]] = | |
summonAll[Tuple.Map[T, Show]].toList.asInstanceOf[List[Show[Any]]] | |
private inline def deriveAll[T <: Tuple]: Tuple = inline erasedValue[T] match { | |
case _: EmptyTuple => EmptyTuple | |
case _: (h *: t) => | |
summonFrom { case given Mirror.Of[`h`] => | |
derived[h] | |
} *: deriveAll[t] | |
} | |
inline def derived[T]( | |
using m: Mirror.Of[T] | |
): Show[T] = new Show[T]: | |
extension (t: T) | |
def show: String = | |
inline m match { | |
case p: Mirror.ProductOf[T] => | |
val label = summonInline[ValueOf[m.MirroredLabel]].value | |
val fields = t.asInstanceOf[Product].productElementNames.toList | |
val values = t.asInstanceOf[Product].productIterator.toList | |
val paramString = | |
if (fields.nonEmpty)(fields | |
.zip(values) | |
.zip(instances[p.MirroredElemTypes])) | |
.map { case ((name, value), show) => | |
s"$name = ${show.show(value)}" | |
} | |
.mkString("(", ", ", ")") | |
else "" | |
s"""$label$paramString""" | |
case s: Mirror.SumOf[T] => | |
deriveAll[s.MirroredElemTypes].toList.asInstanceOf[List[Show[Any]]](s.ordinal(t)).show(t) | |
} | |
enum Permission derives Show: | |
case View | |
case Edit | |
case Both(p: Permission, p2: Permission) | |
import Show.given | |
@main def run = | |
println((Permission.Both(Permission.View, Permission.Edit): Permission).show) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment