[edit]

Applicative GitHub

Whereas a functor allows application of a pure function to a value in a context, an Applicative also allows application of a function in a context to a value in a context.

Applicative is a subclass of Apply, which adds an identity, pure.

Typical imports

import scalaz.tc._
import scalaz.Predef._
import scalaz.Scalaz._

Instance declaration

scala> case class ZipList[A](val value: List[A]) extends AnyVal
defined class ZipList

scala> /* Note that this is _not_ the Applicative instance for List! */
     | implicit val zipListAp: Applicative[ZipList] = instanceOf(new ApplicativeClass[ZipList] {
     |   override def pure[A](a: A): ZipList[A] = ZipList(List(a))
     | 
     |   override def ap[A, B](fa: ZipList[A])(f: ZipList[A => B]): ZipList[B] =
     |     ZipList((fa.value zip f.value).map(t => t._2(t._1)))
     | 
     |   override def map[A, B](fa: ZipList[A])(f: A => B): ZipList[B] =
     |     ZipList(fa.value map f)
     | })
zipListAp: scalaz.tc.Applicative[ZipList] = $anon$1@58a1066d

Usage

scala> val l: ZipList[Int] = 123.pure[ZipList]
l: ZipList[scalaz.Predef.Int] = ZipList(List(123))

scala> l.map(_ + 25)
res1: ZipList[Int] = ZipList(List(148))

scala> val l2 = ZipList(List(17, 19, 23))
l2: ZipList[Int] = ZipList(List(17, 19, 23))

scala> val fs: ZipList[Int => Int] = ZipList(List(_ * 2, _ * 3, _ * 4, _ * 5))
fs: ZipList[scalaz.Predef.Int => scalaz.Predef.Int] = ZipList(List($$Lambda$10728/1620553481@1de594e1, $$Lambda$10729/1177918422@77e447a0, $$Lambda$10730/590664621@72c85b4a, $$Lambda$10731/1087869973@e430e3a))

scala> l2.ap(fs)
res2: ZipList[scalaz.Predef.Int] = ZipList(List(34, 57, 92))

Law

The only law introduced by Applicative in addition to Apply’s laws is:

scala>   def applyIdentity[F[_], A, T](in: F[A])(assert: (F[A], F[A]) => T)(implicit F: Applicative[F]) =
     |     assert(in, F.ap(in)(F.pure((a: A) => a)))
applyIdentity: [F[_], A, T](in: F[A])(assert: (F[A], F[A]) => T)(implicit F: scalaz.tc.Applicative[F])T

That is to say, pure(identity) is an identity for ap.

pure does not “modify” the F[_] context.

Note that a free law (derived for “free” from the type of pure) states:

scala> def freePureMap[F[_]: Applicative, A, B, T](a: A, f: A => B)(assert: (F[B], F[B]) => T): T =
     |   assert(f(a).pure[F], a.pure[F].map(f))
freePureMap: [F[_], A, B, T](a: A, f: A => B)(assert: (F[B], F[B]) => T)(implicit evidence$1: scalaz.tc.Applicative[F])T

As long as no casting or isInstanceOf is done by the implementor, this law is guaranteed and doesn’t necessarily need to be tested.