Skip to content

Instantly share code, notes, and snippets.

@mpilquist
Last active August 29, 2015 14:28
Show Gist options
  • Select an option

  • Save mpilquist/ba9a9fc522a2ed0a0a7b to your computer and use it in GitHub Desktop.

Select an option

Save mpilquist/ba9a9fc522a2ed0a0a7b to your computer and use it in GitHub Desktop.
Port of Travis Brown's covariant sequence for HLists: http://stackoverflow.com/questions/16127360/sequencing-an-hlist
import shapeless._
import shapeless.ops.hlist._
import UnaryTCConstraint._
object inv {
trait Zip[F[_]] {
def pure[A](a: A): F[A]
def zip[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}
trait InvariantFunctor[F[_]] {
def xmap[A, B](fa: F[A])(f: A => B)(g: B => A): F[B]
}
trait InvariantMonoidal[F[_]] extends InvariantFunctor[F] with Zip[F]
object InvariantSequenceFolder extends Poly2 {
implicit def caseInvariantMonoidal[F[_], A, B <: HList](implicit im: InvariantMonoidal[F]) =
at[F[A], F[B]] { (fa, fb) =>
val zipped: F[(A, B)] = im.zip(fa, fb)
im.xmap(zipped)(ab => ab._1 :: ab._2)(abl => (abl.head, abl.tail))
}
}
def isequence[F[_], L <: HList, M <: HList](l: L)(implicit
im: InvariantMonoidal[F],
utcc: *->*[F]#λ[L],
folder: RightFolder.Aux[L, F[HNil], InvariantSequenceFolder.type, F[M]]
): F[M] = {
l.foldRight(im.pure(HNil: HNil))(InvariantSequenceFolder)
}
import scodec.Codec
implicit val codecInvariantMonoidal: InvariantMonoidal[Codec] = new InvariantMonoidal[Codec] {
def pure[A](a: A) = scodec.codecs.ignore(0).xmap(_ => a, _ => ())
def zip[A, B](fa: Codec[A], fb: Codec[B]) = fa ~ fb
def xmap[A, B](fa: Codec[A])(f: A => B)(g: B => A) = fa.xmap(f, g)
}
import scodec.codecs._
val cs = uint8 :: ignore(4) :: utf8_32 :: HNil
val x: Codec[Int :: Unit :: String :: HNil] = isequence(cs)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment