Applicative

Implementation

trait Applicative[F[_]] extends Functor[F] {

  def pure[A](a: A): F[A]

  def ap[A, B](f: F[A => B])(fa: F[A]): F[B]

  def map[A, B](fa: F[A])(f: A => B): F[B] =
    ap(pure(f))(fa)
}

Extension methods

object Applicative {

  import Functor._

  implicit class ApplicativeOps[A, B, F[_]: Applicative](f: F[A => B]) {
    def <*>(fa: F[A]): F[B] =
      implicitly[Applicative[F]].ap(f)(fa)
  }

  implicit class FnCofunctor[A, B](g: A => B) {
    def <%>[F[_]: Functor](x: F[A]) = x map g
  }
}

Laws

From Wikibooks:

pure id <*> v = v                            -- Identity
pure f <*> pure x = pure (f x)               -- Homomorphism
u <*> pure y = pure ($ y) <*> u              -- Interchange
pure (.) <*> u <*> v <*> w = u <*> (v <*> w) -- Composition

Dependencies

Examples