Created
July 6, 2015 10:37
-
-
Save AndreasKostler/d336ff11d26daf674538 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
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