Created
December 20, 2018 16:59
-
-
Save nbenns/4015a250b3fedb1355e22d3fc45c229d to your computer and use it in GitHub Desktop.
Fix a GADT Based List
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 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