Skip to content

Instantly share code, notes, and snippets.

@edmundnoble
Created November 26, 2016 03:47
Show Gist options
  • Save edmundnoble/55aefd0b8f1efb52b2f32f6421f86d14 to your computer and use it in GitHub Desktop.
Save edmundnoble/55aefd0b8f1efb52b2f32f6421f86d14 to your computer and use it in GitHub Desktop.
Freeco
import cats.Functor
import cats.implicits._
sealed trait Freeco[F[_], V, A] {
def eliminate[B](pureElim: V => B, rollElim: (F[Freeco[F, V, A]], A) => B): B
def fold[B](pureElim: V => B, rollElim: (F[V], A) => V)(implicit F: Functor[F]): B
}
case class Pure[F[_], V, A](v: V) extends Freeco[F, V, A] {
override def eliminate[B](pureElim: (V) => B, rollElim: (F[Freeco[F, V, A]], A) => B): B =
pureElim(v)
override def fold[B](pureElim: (V) => B, rollElim: (F[V], A) => V)(implicit F: Functor[F]): B =
pureElim(v)
}
case class Roll[F[_], V, A](roll: F[Freeco[F, V, A]], annot: A) extends Freeco[F, V, A] {
override def eliminate[B](pureElim: (V) => B, rollElim: (F[Freeco[F, V, A]], A) => B): B =
rollElim(roll, annot)
override def fold[B](pureElim: (V) => B, rollElim: (F[V], A) => V)(implicit F: Functor[F]): B = {
pureElim(rollElim(roll.map(_.fold(pureElim, rollElim)), annot))
}
}
object Freeco {
def build[F[_], V, A](seed: V, coalg: V => Option[(F[V], A)])(implicit F: Functor[F]): Freeco[F, V, A] = {
coalg(seed).fold[Freeco[F, V, A]](Pure(seed)) { case (grow, annot) =>
Roll(grow.map(build(_, coalg)), annot)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment