Skip to content

Instantly share code, notes, and snippets.

@ukitaka
Last active February 14, 2017 02:13
Show Gist options
  • Save ukitaka/080375639a4b52c273bdef2a1c1e44f7 to your computer and use it in GitHub Desktop.
Save ukitaka/080375639a4b52c273bdef2a1c1e44f7 to your computer and use it in GitHub Desktop.
ApplicativeとApplicativeの合成
trait Applicative[F[_]] extends Functor[F] {
// この2つが必要
def point[A](a: A): F[A]
def ap[A, B](a: F[A])(f: F[A => B]): F[B]
// pureはpointのalias?
def pure[A](a: A): F[A] = point(a)
// 以下はap/pointを使って実装できるもの
def apF[A,B](f: => F[A => B]): F[A] => F[B] = ap(_)(f)
def apply2[A, B, C](fa: => F[A], fb: => F[B])(f: (A, B) => C): F[C] =
ap(fb)(ap(fa)(point(f.curried)))
def ap2[A,B,C](fa: => F[A], fb: => F[B])(f: F[(A,B) => C]): F[C] =
ap(fb)(ap(fa)(map(f)(_.curried)))
// mapはapとpointから実装できる
def map[A, B](fa: F[A])(f: A => B): F[B] = ap(fa)(point(f))
}
def composeApplicative[F[_]: Applicative, G[_]: Applicative] = new Applicative[({ type f[x] = F[G[x]] })#f] {
val F = implicitly[Applicative[F]]
val G = implicitly[Applicative[G]]
def point[A](a: A): F[G[A]] = F.point(G.point(a))
def ap[A, B](a: F[G[A]])(f: F[G[A => B]]): F[G[B]] = F.apply2(a, f)((ga, g) => G.ap(ga)(g))
}
@ukitaka
Copy link
Author

ukitaka commented Feb 14, 2017

implicit val optionalApplicative = new Applicative[Option] {
  override def point[A](a: A) = Some(a)
  override def ap[A, B](a: Option[A])(f: Option[A => B]): Option[B] = f match {
    case Some(f) => a.map(f)
    case None => None
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment