Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Created March 14, 2015 01:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save xuwei-k/9d815c756744e8b43fb7 to your computer and use it in GitHub Desktop.
Save xuwei-k/9d815c756744e8b43fb7 to your computer and use it in GitHub Desktop.
deriving Foldable in Scala
libraryDependencies += "com.chuusai" %% "shapeless" % "2.2.0-RC1"
scalaVersion := "2.11.6"
info] Running DerivingFoldableExample
[error] (run-main-15) java.lang.StackOverflowError
java.lang.StackOverflowError
at scala.runtime.BoxesRunTime.boxToInteger(BoxesRunTime.java:69)
at DerivingFoldableExample$$anonfun$main$1.apply(Foldable.scala:59)
at Foldable$$anon$1.foldLeft(Foldable.scala:13)
at Foldable$$anon$2.foldLeft(Foldable.scala:20)
at Foldable$$anon$4.foldLeft(Foldable.scala:38)
at Foldable$$anon$3.foldLeft(Foldable.scala:29)
at Foldable$$anon$4.foldLeft(Foldable.scala:38)
at Foldable$$anon$2.foldLeft(Foldable.scala:20)
at Foldable$$anon$2.foldLeft(Foldable.scala:20)
at Foldable$$anon$4.foldLeft(Foldable.scala:38)
at Foldable$$anon$3.foldLeft(Foldable.scala:29)
at Foldable$$anon$4.foldLeft(Foldable.scala:38)
at Foldable$$anon$2.foldLeft(Foldable.scala:20)
at Foldable$$anon$2.foldLeft(Foldable.scala:20)
at Foldable$$anon$4.foldLeft(Foldable.scala:38)
at Foldable$$anon$3.foldLeft(Foldable.scala:29)
at Foldable$$anon$4.foldLeft(Foldable.scala:38)
at Foldable$$anon$2.foldLeft(Foldable.scala:20)
at Foldable$$anon$2.foldLeft(Foldable.scala:20)
import shapeless._
trait Foldable[F[_]] {
def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B): B
}
object Foldable extends Foldable0 {
def apply[F[_]](implicit F: Lazy[Foldable[F]]): Foldable[F] = F.value
implicit val idFoldable: Foldable[Id] =
new Foldable[Id] {
def foldLeft[A, B](fa: A, b: B)(f: (B, A) => B) =
f(b, fa)
}
implicit def hcons[F[_]](implicit F: IsHCons1[F, Foldable, Foldable]): Foldable[F] =
new Foldable[F] {
override def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B) = {
val (hd, tl) = F.unpack(fa)
F.ft.foldLeft(tl, F.fh.foldLeft(hd, b)(f))(f)
}
}
implicit def ccons[F[_]](implicit F: IsCCons1[F, Foldable, Foldable]): Foldable[F] =
new Foldable[F] {
def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B) =
F.unpack(fa) match {
case Left(l) =>
F.fh.foldLeft(l, b)(f)
case Right(r) =>
F.ft.foldLeft(r, b)(f)
}
}
implicit def generic[F[_]](implicit F: Generic1[F, Foldable]): Foldable[F] =
new Foldable[F] {
def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) => B) =
F.fr.foldLeft(F.to(fa), b)(f)
}
}
sealed abstract class Foldable0 {
implicit def constFoldable[T]: Foldable[Const[T]#λ] =
new Foldable[Const[T]#λ] {
override def foldLeft[A, B](fa: T, b: B)(f: (B, A) => B) =
b
}
}
sealed abstract class IList[A]
final case class ICons[A](head: A, tail: IList[A]) extends IList[A]
final case class INil[A]() extends IList[A]
object DerivingFoldableExample {
def main(args: Array[String]): Unit = {
val list = (1 to 100000).foldLeft(ICons(0, INil())){ (acc, i) => ICons(i, acc) }
println(Foldable[IList].foldLeft(list, 0)(_ + _))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment