Skip to content

Instantly share code, notes, and snippets.

@milessabin
Created April 12, 2012 08:31
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 milessabin/2365624 to your computer and use it in GitHub Desktop.
Save milessabin/2365624 to your computer and use it in GitHub Desktop.
Witnessing that there is a natural transformation between two HLists
object WitnessNatT {
import shapeless._
import TypeOperators._
trait NatTRel[L1 <: HList, F[_], L2 <: HList, G[_]]
object NatTRel {
type ~??>[F[_], G[_]] = {
type λ[L1 <: HList, L2 <: HList] = NatTRel[L1, F, L2, G]
}
implicit def hnilUnaryTC[F[_], G[_]] = new NatTRel[HNil, F, HNil, G] {}
implicit def hlistUnaryTC0[H1, T1 <: HList, H2, T2 <: HList, G[_]](implicit e : NatTRel[T1, Id, T2, G]) =
new NatTRel[H1 :: T1, Id, G[H2] :: T2, G] {}
implicit def hlistUnaryTC1[H1, T1 <: HList, F[_], H2, T2 <: HList](implicit e : NatTRel[T1, F, T2, Id]) =
new NatTRel[F[H1] :: T1, F, H2 :: T2, Id] {}
implicit def hlistUnaryTC2[H1, T1 <: HList, F[_], H2, T2 <: HList, G[_]](implicit e : NatTRel[T1, F, T2, G]) =
new NatTRel[F[H1] :: T1, F, G[H2] :: T2, G] {}
}
import NatTRel._
def f[L1 <: HList, L2 <: HList](l1: L1)(l2: L2)(implicit e: (Option ~??> Id)#λ[L1, L2]) = l2
def usage = {
implicitly[NatTRel[Option[String] :: HNil, Option, Set[String] :: HNil, Set]]
implicitly[NatTRel[Option[String] :: HNil, Option, String :: HNil, Id]]
implicitly[NatTRel[String :: HNil, Id, Option[String] :: HNil, Option]]
f((None : Option[Int]) :: Option("a") :: HNil)(1 :: "b" :: HNil)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment