Skip to content

Instantly share code, notes, and snippets.

@YoEight
Created July 31, 2012 12:00
Show Gist options
  • Save YoEight/3216489 to your computer and use it in GitHub Desktop.
Save YoEight/3216489 to your computer and use it in GitHub Desktop.
Coproduct implicit resolution
object coprod {
trait Functor[F[_]]{
def map[A, B](fa: F[A])(f: A => B): F[B]
}
implicit val optionFunctor = new Functor[Option]{
def map[A, B](fa: Option[A])(f: A => B) = fa map f
}
implicit val listFunctor = new Functor[List]{
def map[A, B](fa: List[A])(f: A => B) = fa map f
}
implicit val streamFunctor = new Functor[Stream]{
def map[A, B](fa: Stream[A])(f: A => B) = fa map f
}
/*implicit def coproductFunctor[F[_], G[_]](implicit F: Functor[F], G: Functor[G]) = new Functor[coproduct[F, G]#ap]{
def map[A, B](ea: Either[F[A], G[A]])(f: A => B) = ea match {
case Left(fa) => Left(F.map(fa)(f))
case Right(ga) => Right(G.map(ga)(f))
}
}
trait coproduct[F[_], G[_]]{
type or[H[_]] = coproduct[({type f[x] = Either[F[x], G[x]]})#f, H]
type ap[A] = Either[F[A], G[A]]
}*/
trait Coproduct[F[_], G[_], A]{
def fold[Z](inl: (=> F[A]) => Z, inr: (=> G[A]) => Z): Z
def map[B](f: A => B)(implicit F: Functor[F], G: Functor[G]): Coproduct[F, G, B] = this match {
case Inl(fa) => Inl(F.map(fa)(f))
case Inr(ga) => Inr(G.map(ga)(f))
}
}
object Inl {
def apply[F[_], G[_], A](v: => F[A]): Coproduct[F, G, A] = new Coproduct[F, G, A]{
def fold[Z](inl: (=> F[A]) => Z, inr: (=> G[A]) => Z) = inl(v)
}
def unapply[F[_], G[_], A](co: Coproduct[F, G, A]) =
co.fold(Some(_), _ => None)
}
object Inr {
def apply[F[_], G[_], A](v: => G[A]): Coproduct[F, G, A] = new Coproduct[F, G, A]{
def fold[Z](inl: (=> F[A]) => Z, inr: (=> G[A]) => Z) = inr(v)
}
def unapply[F[_], G[_], A](co: Coproduct[F, G, A]) =
co.fold(_ => None, Some(_))
}
trait :+:[F[_], G[_]]{
type ap[A] = Coproduct[F, G, A]
}
implicit def coproductFunctor[F[_], G[_]](implicit F: Functor[F], G: Functor[G]) = new Functor[(F :+: G)#ap]{
def map[A, B](fa: Coproduct[F, G, A])(f: A => B) = fa map f
}
type To = (Option :+: Stream)#ap :+: List
val f = implicitly[Functor[((Option :+: Stream)#ap :+: List)#ap]] // error
val g = implicitly[Functor[(Option :+: Stream)#ap]] // works
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment