Skip to content

Instantly share code, notes, and snippets.

@vivanov
Created May 16, 2015 16:24
Show Gist options
  • Save vivanov/ea157323a0021e2d8f98 to your computer and use it in GitHub Desktop.
Save vivanov/ea157323a0021e2d8f98 to your computer and use it in GitHub Desktop.
package ru.lester.shapeless
import shapeless._
object ShowGeneric {
trait Show[T] {
def show(t: T): String
}
object Show extends LabelledTypeClassCompanion[Show] {
implicit def intShow: Show[Int] = new Show[Int] {
override def show(i: Int): String = i.toString
}
implicit def booleanShow: Show[Boolean] = new Show[Boolean] {
override def show(b: Boolean): String = b.toString
}
implicit def listShow[A](implicit showA: Show[A]): Show[List[A]] = new Show[List[A]] {
override def show(l: List[A]): String = l.map(showA.show).mkString("List(", ", ", ")")
}
object typeClass extends LabelledTypeClass[Show] {
override def emptyProduct: Show[HNil] = new Show[HNil] {
override def show(t: HNil): String = ""
}
override def product[H, T <: HList](name: String, sh: Show[H], st: Show[T]): Show[H :: T] = new Show[H :: T] {
override def show(t: H :: T): String = {
val head = s"$name = ${sh.show(t.head)}"
val tail = st.show(t.tail)
if(tail.isEmpty) head else s"$head, $tail"
}
}
override def coproduct[L, R <: Coproduct](name: String, cl: => Show[L], cr: => Show[R]): Show[L :+: R] = new Show[L :+: R] {
override def show(t: L :+: R): String = t match {
case Inl(l) => s"$name(${cl.show(l)})"
case Inr(r) => cr.show(r)
}
}
override def emptyCoproduct: Show[CNil] = new Show[CNil] {
override def show(t: CNil): String = ""
}
override def project[F, G](instance: => Show[G], to: F => G, from: G => F): Show[F] = new Show[F] {
override def show(t: F): String = instance.show(to(t))
}
}
}
implicit class ShowOps[T](t: T)(implicit showT: Show[T]) {
def show: String = showT.show(t)
}
sealed trait Whatever
case class IntBool(i: Int, b: Boolean) extends Whatever
case class BoolInt(b: Boolean, i: Int) extends Whatever
case class BoolListInt(b: Boolean, l: List[Int]) extends Whatever
def showWhatever(whatever: Whatever)(implicit showWhatever: Show[Whatever]): String = {
showWhatever.show(whatever)
}
val stringIntBool = IntBool(1, true).show
val stringBoolList = BoolListInt(false, List(1, 2, 3)).show
val stringBoolInt = BoolInt(false, 100).show
//val stringShowWahtever = showWhatever(BoolInt(false, 100)) // doesn't compile when assigned to val for some reason (see http://stackoverflow.com/q/30107241/754913 ), works perfectly if referenced outside
//BoolInt(false, 100).show // compiles
//showWhatever(BoolInt(false, 100)) // compiles
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment