Skip to content

Instantly share code, notes, and snippets.

@shengc
Last active January 5, 2017 04:15
Show Gist options
  • Save shengc/2f5f3610035678118a0b4cb0f6f5d66d to your computer and use it in GitHub Desktop.
Save shengc/2f5f3610035678118a0b4cb0f6f5d66d to your computer and use it in GitHub Desktop.
 -- In Haskell

import Control.Applicative

newtype Compose f g a = Compose { getCompose :: f (g a) }

instance (Functor f, Functor g) => Functor (Compose f g) where
  fmap f (Compose fga) = Compose $ (fmap . fmap) f fga

instance (Applicative f, Applicative g) => Applicative (Compose f g) where
  pure = Compose . pure . pure
  Compose f <*> Compose a = Compose $ (liftA2 . liftA2) ($) f a

instance (Foldable f, Foldable g) => Foldable (Compose f g) where
  foldMap f (Compose fga)= (foldMap . foldMap) f fga

instance (Traversable f, Traversable g) => Traversable (Compose f g) where
  traverse f (Compose fga) = Compose <$> (traverse . traverse) f fga
// In Scala

import scala.language.higherKinds

trait Functor[F[_]] {
  def fmap[A, B](fa: F[A])(f: A => B): F[B]
}

object Functor {
  def apply[F[_]](implicit fa: Functor[F]): Functor[F] = fa

  implicit val listF : Functor[List] = new Functor[List] {
    def fmap[A, B](fa: List[A])(f: A => B) = fa.map(f)
  }
}

implicit def fc[F[_]: Functor, G[_]: Functor] : Functor[({type M[A] = F[G[A]]})#M] = new Functor[({type M[A] = F[G[A]]})#M] {
  def fmap[A, B](fga: F[G[A]])(f: A => B): F[G[B]] = Functor[F].fmap(fga)(Functor[G].fmap(_)(f))
}

def curry[A, B, C](f: (A, B) => C): A => B => C =
  a => b => f(a, b)

trait Applicative[F[_]] extends Functor[F] {
  def pure[A](a: => A): F[A]
  def apply[A, B](fab: F[A => B])(fa: => F[A]): F[B] = map2(fab)(fa)(_(_))
  def map2[A, B, C](fa: F[A])(fb: => F[B])(f: (A, B) => C): F[C] = {
    val ff = pure(curry(f))
    apply(apply(ff)(fa))(fb)
  }
  override def fmap[A, B](fa: F[A])(f: A => B): F[B] = {
    val ff = pure(f)
    apply(ff)(fa)
  }
}

object Applicative {
  def apply[F[_]](implicit fa: Applicative[F]): Applicative[F] = fa

  implicit val listA : Applicative[List] = new Applicative[List] {
    def pure[A](a: => A) = List(a)
    override def apply[A, B](fab: List[A => B])(fa: => List[A]): List[B] = fab.flatMap(f => fa.map(f(_)))
  }
}

implicit def ac[F[_]: Applicative, G[_]: Applicative] : Applicative[({type M[A] = F[G[A]]})#M] = new Applicative[({type M[A] = F[G[A]]})#M] {
  def pure[A](a: => A) = Applicative[F].pure(Applicative[G].pure(a))
  override def map2[A, B, C](fa: F[G[A]])(fb: => F[G[B]])(f: (A, B) => C): F[G[C]] =
    Applicative[F].map2(fa)(fb)(Applicative[G].map2(_)(_)(f))
}

trait Monoid[A] {
  def mempty : A
  def mappend(a1: A, a2: => A): A
}

object Monoid {
  def apply[A](implicit ma: Monoid[A]): Monoid[A] = ma
}

trait Foldable[F[_]] {
  def foldMap[A, B: Monoid](f: A => B)(fa: => F[A]): B
  def fold[A : Monoid](fa: => F[A]): A = foldMap((a: A) => a)(fa)
}

object Foldable {
  def apply[F[_]](implicit f: Foldable[F]): Foldable[F] = f

  implicit val listF : Foldable[List] = new Foldable[List] {
    def foldMap[A, B: Monoid](f: A => B)(fa: => List[A]): B =
      fa.foldRight(Monoid[B].mempty)((a, b) => Monoid[B].mappend(f(a), b))
  }
}

implicit def fc[F[_]: Foldable, G[_]: Foldable]: Foldable[({type M[A] = F[G[A]]})#M] = new Foldable[({type M[A] = F[G[A]]})#M] {
  def foldMap[A, B : Monoid](f: A => B)(fga: => F[G[A]]): B =
    Foldable[F].foldMap(Foldable[G].foldMap(f)(_ : G[A]))(fga)
}

trait Traversable[F[_]] {
  def traverse[G[_]: Applicative, A, B](f: A => G[B])(fa: => F[A]): G[F[B]]
}

object Traversable {
  def apply[F[_]](implicit ta: Traversable[F]): Traversable[F] = ta

  implicit val listT : Traversable[List] = new Traversable[List] {
    def traverse[G[_]: Applicative, A, B](f: A => G[B])(fa: => List[A]): G[List[B]] =
      Functor[List].fmap(fa)(f).foldRight(Applicative[G].pure(List.empty[B]))(Applicative[G].map2(_)(_)(_ :: _))
  }
}

implicit def tc[F[_]: Traversable, G[_]: Traversable]: Traversable[({type M[A] = F[G[A]]})#M] = new Traversable[({type M[A] = F[G[A]]})#M] {
  def traverse[H[_]: Applicative, A, B](f: A => H[B])(fga: => F[G[A]]): H[F[G[B]]] =
    Traversable[F].traverse(Traversable[G].traverse(f)(_: G[A]))(fga)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment