Skip to content

Instantly share code, notes, and snippets.

@scarf005
Created March 20, 2025 15:15
Show Gist options
  • Save scarf005/739c0e632df606ce904e4da8fcc95cea to your computer and use it in GitHub Desktop.
Save scarf005/739c0e632df606ce904e4da8fcc95cea to your computer and use it in GitHub Desktop.
// https://xebia.com/blog/how-to-derive-type-class-instances-with-shapeless-3/
//> using dep org.typelevel::shapeless3-deriving::3.5.0
package deriving
import shapeless3.deriving.*
trait Show[A]:
def show(a: A): String
object Show:
given Show[Int] = _.toString
given Show[Boolean] = _.toString
given Show[String] = identity(_)
def deriveShowProduct[
A: {Labelling as labelling, ([x] =>> K0.ProductInstances[Show, x]) as pInst},
]: Show[A] =
(a: A) =>
labelling.elemLabels.zipWithIndex
.map { (label, index) =>
val value = pInst.project(a)(index)([t] => (st: Show[t], pt: t) => st.show(pt))
s"$label = $value"
}
.mkString(s"${labelling.label}(", ", ", ")")
def deriveShowSum[A: ([x] =>> K0.CoproductInstances[Show, x]) as cInst]: Show[A] =
(a: A) => cInst.fold(a)([a] => (st: Show[a], a: a) => st.show(a))
inline given derived[A: K0.Generic as gen]: Show[A] =
gen.derive(deriveShowProduct, deriveShowSum)
extension [A: Show as s](a: A) inline def show: String = s.show(a)
case class Pos(x: Int, y: Int) derives Show
enum Expr derives Show:
case Var(name: String)
case Add(left: Expr, right: Expr)
case Mul(left: Expr, right: Expr)
@main def main() =
println(Pos(3, 4).show)
println(Expr.Add(Expr.Var("x"), Expr.Mul(Expr.Var("y"), Expr.Var("z"))).show)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment