Skip to content

Instantly share code, notes, and snippets.

@sir-wabbit
Created November 28, 2019 00:03
Show Gist options
  • Save sir-wabbit/9761ee88f5cf476c86b58e519e17a871 to your computer and use it in GitHub Desktop.
Save sir-wabbit/9761ee88f5cf476c86b58e519e17a871 to your computer and use it in GitHub Desktop.
import cats.Eq
trait Eq1[F[_]] {
def eqv1[A](x: F[A], y: F[A])(implicit A: Eq[A]): Boolean
}
final case class Fix[F[_]](unfix: F[Fix[F]])
object Fix {
implicit def eqv[F[_]: Eq1]: Eq[Fix[F]] = new Eq[Fix[F]] {
def eqv(x: Fix[F], y: Fix[F]): Boolean =
implicitly[Eq1[F]].eqv1[Fix[F]](x.unfix, y.unfix)
}
}
trait Mu[F[_]] {
def run[Z](f: F[Z] => Z): Z
def toFix: Fix[F] = run(Fix[F](_))
}
object Mu {
implicit def eqv[F[_]: Eq1]: Eq[Mu[F]] = new Eq[Mu[F]] {
def eqv(x: Mu[F], y: Mu[F]): Boolean = Fix.eqv.eqv(x.toFix, y.toFix)
}
}
sealed trait ListF[+A, +L]
final case object NilF extends ListF[Nothing, Nothing]
final case class ConsF[H, T](head: H, tail: T) extends ListF[H, T]
object ListF {
implicit def eq1[A](implicit A: Eq[A]): Eq1[ListF[A, ?]] = new Eq1[ListF[A, ?]] {
def eqv1[L](x: ListF[A, L], y: ListF[A, L])(implicit L: Eq[L]): Boolean =
(x, y) match {
case (NilF, NilF) => true
case (ConsF(h1, t1), ConsF(h2, t2)) => A.eqv(h1, h2) && L.eqv(t1, t2)
}
}
}
// final case class FooF[+A](i: Int, tail: A)
// type TupleF[F[_], G[_], A] = (F[A], G[A])
// type EitherF[F[_], G[_], A] = Either[F[A], G[A]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment