Skip to content

Instantly share code, notes, and snippets.

@AndreasKostler
Created July 6, 2015 10:37
Show Gist options
  • Save AndreasKostler/d336ff11d26daf674538 to your computer and use it in GitHub Desktop.
Save AndreasKostler/d336ff11d26daf674538 to your computer and use it in GitHub Desktop.
import shapeless._
import syntax._
import poly._
object LeftFolderOps {
trait LeftFolder[C <: Coproduct, In, F] extends Serializable {
def apply(c: C, in: In): In
}
object LeftFolder {
def apply[C <: Coproduct, In, F](implicit folder: LeftFolder[C, In, F]) = folder
implicit def hdLeftFolder[H, In, F]
(implicit f: Case2.Aux[F, In, H, In]): LeftFolder[H :+: CNil, In, F] = new LeftFolder[H :+: CNil, In, F] {
def apply(c: H :+: CNil, in: In): In = c match {
case Inl(h) => f(in, h)
case Inr(t) => in
}
}
implicit def tlLeftFolder[H, T <: Coproduct, In, F]
(implicit st: LeftFolder[T, In, F], f: Case2.Aux[F, In, H, In]): LeftFolder[H :+: T, In, F] = new LeftFolder[H :+: T, In, F] {
def apply(c: H :+: T, in: In) =
c match {
case Inl(h) => f(in, h)
case Inr(t) => st(t, in)
}
}
}
}
final class LeftFolderOps[C <: Coproduct](c: C) extends Serializable {
def foldLeft[In](z: In)(op: Poly)(implicit folder: LeftFolderOps.LeftFolder[C, In, op.type]): In = folder(c, z)
}
object CoproductLeftFolderSyntax {
implicit def coproductOps[C <: Coproduct](c: C): LeftFolderOps[C] = new LeftFolderOps(c)
}
import CoproductLeftFolderSyntax._
type IS = Int :+: String :+: Boolean :+: CNil
val isi = Coproduct[IS](10)
val iss = Coproduct[IS]("foo")
val isb = Coproduct[IS](true)
object size extends Poly1 {
implicit def caseInt = at[Int](_ => 1)
implicit def caseString = at[String](_.length)
implicit def caseBoolean = at[Boolean](_ => 42)
}
object wonkyAddSize extends Poly2 {
implicit def default[T](implicit st: size.Case.Aux[T, Int]) =
at[Int, T] { (acc, t) => if (acc > 42) acc - size(t) else acc + size(t) }
}
isi.foldLeft(0)(wonkyAddSize) // 1
iss.foldLeft(42)(wonkyAddSize) // 45
isb.foldLeft(43)(wonkyAddSize) // 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment