All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sjc.delta.Reify.scala Maven / Gradle / Ivy

The newest version!
package sjc.delta

import scala.reflect.ClassTag


sealed trait Reified {
  def asString: String
}

case class ReifiedValue(value: String) extends Reified {
  def asString: String = value
}

object ReifiedProduct {
  def caseClass(name: String, values: List[Reified]): Reified = ReifiedProduct(values, s"$name(", ", ", ")")
  def hlist(values: List[Reified]): Reified = ReifiedProduct(values, "", " :: ", " :: HNil")
}

case class ReifiedProduct(values: List[Reified], start: String, sep: String, end: String) extends Reified {
  def ::(head: Reified): ReifiedProduct = copy(head :: values)
  def asString: String = values.map(_.asString).mkString(start, sep, end)
}

trait Reify[A] {
  def asString(value: A): String = apply(value).asString
  def apply(value: A): Reified

  def contramap[B](f: B => A, start: String = null, end: String = ")")(implicit ct: ClassTag[B]): Reify[B] =
    new Reify.Contramapped[A, B](f, this, Option(start).getOrElse(ct.runtimeClass.getSimpleName), end)
}

object Reify {
  implicit class ReifyOps[A](val value: A) extends AnyVal {
    def reify(implicit reify: Reify[A]): Reified = reify(value)
  }

  def apply[A](implicit reify: Reify[A]): Reify[A] = reify

  implicit val booleanReify: Reify[Boolean] = reifyA[Boolean]

  implicit val charReify: Reify[Char] = reify[Char]("'" + _ + "'")

  implicit val doubleReify: Reify[Double] = reifyA[Double]

  implicit val floatReify: Reify[Float] = reify[Float](value => s"${value}F")

  implicit val intReify: Reify[Int] = reifyA[Int]

  implicit val longReify: Reify[Long] = reify[Long](value => s"${value}L")

  implicit val stringReify: Reify[String] = reify[String]("\"" + _ + "\"")

  implicit def optionReify[A](implicit reifyA: Reify[A]): Reify[Option[A]] =
    reify[Option[A]](_.map(reifyA.asString).toString)

  implicit def eitherReify[L, R](implicit reifyL: Reify[L], reifyR: Reify[R]): Reify[Either[L, R]] =
    reify[Either[L, R]](_.fold(l => s"Left(${reifyL.asString(l)})", r => s"Right(${reifyR.asString(r)})"))

  implicit def listReify[A](implicit reifyA: Reify[A]): Reify[List[A]] =
    reify[List[A]](_.map(reifyA.asString).toString)

  implicit def setReify[A](implicit reifyA: Reify[A]): Reify[Set[A]] =
    reify[Set[A]](_.map(reifyA.asString).toString)

  implicit def mapReify[K, V](implicit reifyK: Reify[K], reifyV: Reify[V]): Reify[Map[K, V]] =
    reify[Map[K, V]](_.map { case (k, v) => (reifyK.asString(k), reifyV.asString(v)) }.toString)

  private class Contramapped[A, B](f: B => A, reifyA: Reify[A], start: String, end: String) extends Reify[B] {
    def apply(value: B): Reified = ReifiedProduct(List(reifyA(f(value))), start + "(", ", ", end)
  }

  def reifyA[A]: Reify[A] = reify[A](_.toString)

  def reify[A](f: A => String): Reify[A] = reifyIt(a => ReifiedValue(f(a)))

  def reifyIt[A](f: A => Reified): Reify[A] = new Reify[A] {
    def apply(value: A): Reified = f(value)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy