Skip to content

Instantly share code, notes, and snippets.

@rossabaker
Created October 1, 2021 14:39
Show Gist options
  • Save rossabaker/6a5b4be9ddd61b8ae0ca1346f61cb06e to your computer and use it in GitHub Desktop.
Save rossabaker/6a5b4be9ddd61b8ae0ca1346f61cb06e to your computer and use it in GitHub Desktop.
scala> import cats.implicits._
import cats.implicits._
scala> case class Abcde(a: String, b: String, c: String, d: String, e: String)
defined class Abcde
scala> val fruit = Abcde("Apple", "Banana", "Coconut", "Durian", "Elderberry")
fruit: Abcde = Abcde(Apple,Banana,Coconut,Durian,Elderberry)
scala> val sb: SB[Abcde] = (SB.string, SB.string, SB.string, SB.string, SB.string).contramapN(abcde => (abcde.a, abcde.b, abcde.c, abcde.d, abcde.e))
sb: org.http4s.bench.SB[Abcde] = org.http4s.bench.SB$$anon$1@375f6d4a
scala> sb.render(fruit)
res0: String = AppleBananaCoconutDurianElderberry
import cats._
// A pure functional, contravariant monoidal string builder
sealed trait SB[A] {
final def render(a: A): String = {
val sb = new StringBuilder
renderInternal(sb, a)
sb.toString
}
def contramap[B](f: B => A): SB[B] =
SB.instance[B]((sb, b) => renderInternal(sb, f(b)))
def product[B](that: SB[B]) =
SB.instance[(A, B)] { (sb, ab) =>
this.renderInternal(sb, ab._1)
that.renderInternal(sb, ab._2)
}
protected def renderInternal(sb: StringBuilder, a: A): Unit
}
object SB {
def instance[A](f: (StringBuilder, A) => Unit) = {
new SB[A] {
protected def renderInternal(sb: StringBuilder, a: A) = f(sb, a)
}
}
val unit: SB[Unit] = SB.instance[Unit]((_, _) => ())
val string: SB[String] = SB.instance[String](_.append(_))
implicit val catsInstancesForSB: ContravariantMonoidal[SB] =
new ContravariantMonoidal[SB] {
def contramap[A, B](fa: SB[A])(f: B => A) = fa.contramap(f)
val unit = SB.unit
def product[A, B](fa: SB[A], fb: SB[B]): SB[(A, B)] = fa.product(fb)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment