Created
May 16, 2015 16:24
-
-
Save vivanov/ea157323a0021e2d8f98 to your computer and use it in GitHub Desktop.
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
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