Skip to content

Instantly share code, notes, and snippets.

@travisbrown
Created October 2, 2015 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save travisbrown/25ba8580f4661711622f to your computer and use it in GitHub Desktop.
Save travisbrown/25ba8580f4661711622f to your computer and use it in GitHub Desktop.
import shapeless._
import shapeless.ops.coproduct._
import cats.~>
trait ExtendRightT[F[_] <: Coproduct, G[_]] {
type Out[_] <: Coproduct
def apply[H[_]](f: F ~> H, g: G ~> H): Out ~> H
}
object ExtendRightT {
type Aux[F[_] <: Coproduct, G[_], Out0[_] <: Coproduct] = ExtendRightT[F, G] { type Out[x] = Out0[x] }
implicit def extendRightTSingleton[F[_], G[_]]: Aux[
({ type L[A] = F[A] :+: CNil })#L,
G,
({ type L[A] = F[A] :+: G[A] :+: CNil })#L
] = new ExtendRightT[({ type L[A] = F[A] :+: CNil })#L, G] {
type Out[x] = F[x] :+: G[x] :+: CNil
def apply[H[_]](f: ({ type L[A] = F[A] :+: CNil })#L ~> H, g: G ~> H): Out ~> H =
new (Out ~> H) {
def apply[A](c: F[A] :+: G[A] :+: CNil): H[A] =
c match {
case Inl(fa) => f(Inl(fa))
case Inr(Inl(ga)) => g(ga)
}
}
}
implicit def extendRightTCoproduct[
F[_],
T[_] <: Coproduct,
G[_]
](implicit extendRightT: ExtendRightT[T, G]): Aux[
({ type L[A] = F[A] :+: T[A] })#L,
G,
({ type L[A] = F[A] :+: extendRightT.Out[A] })#L
] = new ExtendRightT[({ type L[A] = F[A] :+: T[A] })#L, G] {
type Out[x] = F[x] :+: extendRightT.Out[x]
def apply[H[_]](f: ({ type L[A] = F[A] :+: T[A] })#L ~> H, g: G ~> H): Out ~> H =
new (Out ~> H) {
def apply[A](c: F[A] :+: extendRightT.Out[A]): H[A] =
c match {
case Inl(fa) => f(Inl(fa))
case Inr(ta) => extendRightT(
new (T ~> H) {
def apply[B](b: T[B]): H[B] = f(Inr(b))
},
g
)(ta)
}
}
}
}
def or2[F[_] <: Coproduct, G[_], H[_]](f: F ~> H, g: G ~> H)(implicit
e: ExtendRightT[F, G]
): e.Out ~> H = e(f, g)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment