Skip to content

Instantly share code, notes, and snippets.

@nbenns
Created December 20, 2018 16:59
Show Gist options
  • Save nbenns/4015a250b3fedb1355e22d3fc45c229d to your computer and use it in GitHub Desktop.
Save nbenns/4015a250b3fedb1355e22d3fc45c229d to your computer and use it in GitHub Desktop.
Fix a GADT Based List
import scala.language.higherKinds
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
object Functor {
def apply[F[_]](implicit fun: Functor[F]): Functor[F] = fun
implicit class FunctorOps[F[_]: Functor, A](fa: F[A]) {
def map[B](f: A => B): F[B] = Functor[F].map(fa)(f)
}
}
sealed trait GListF[R]
case class GNilF[R]() extends GListF[R]
case class GConsF[H, T](head: H, tail: T) extends GListF[T]
object GListF {
implicit val glistFFunctor: Functor[GListF] = new Functor[GListF] {
override def map[A, B](fa: GListF[A])(f: A => B): GListF[B] = fa match {
case GNilF() => GNilF()
case GConsF(h, t) => GConsF(h, f(t))
}
}
}
case class Fix[F[_]](unFix: F[Fix[F]])
type FAlgebra[F[_], A] = F[A] => A
type PAlgebra[F[_], A] = F[(Fix[F], A)] => A
import Functor._
def cataMorphism[F[_]: Functor, A](ff: Fix[F], f: FAlgebra[F, A]): A = f(ff.unFix.map(cataMorphism(_, f)))
implicit class FixOps[F[_]: Functor](ff: Fix[F]) {
def cata[A](f: FAlgebra[F, A]): A = cataMorphism[F, A](ff, f)
def para[A](p: PAlgebra[F, A]): A = {
val f: FAlgebra[F, (Fix[F], A)] = fa => (Fix(Functor[F].map(fa)(_._1)), p(fa))
cataMorphism[F, (Fix[F], A)](ff, f)._2
}
}
import GListF._
val meh: Fix[GListF] = Fix(GConsF("meow", Fix(GConsF(5, Fix(GConsF("bob", Fix(GNilF())))))))
val dosomething: PAlgebra[GListF, Int] = {
case hcons: GConsF[h, (Fix[GListF], Int)] =>
println(hcons.tail._1)
hcons.head match {
case h: Int => hcons.tail._2 + h
case h: String => hcons.tail._2 + h.length
}
case GNilF() => 0
}
val a = meh.para(dosomething)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment