Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is Applicative Builder

I am scala and functional newbie and trying to learn applicatives.

val o1 = Some(1)
val o2 = Some(2)
val o3 = Some(3)
val result = (o1 |@| o2 |@| o3) {_ + _ + _}

There is a very good read about Applicatives and Functors here

As per this blog,

Operator |@| is the product operation

and

combining your applicatives into a product by using |@| results in an ApplicativeBuilder which takes a function to perform on the product (since product + map is a very common use case)

I am finding it very difficult to understand above two statements from the blog. Any example with code in scala to understand this will be helpful.

like image 441
mogli Avatar asked Sep 11 '17 09:09

mogli


1 Answers

I think the key take away from the post, which should help reason about applicative functors is this sentence:

Hey, so you got your function wrapped into a bit of a context, huh? Not to worry, I know how to apply those kind of wrapped functions

Applicative provides a way of applying a function wrapped in a context over other wrapped values.

|@| and the underlying type ApplicativeBuilder are just scalazs way of constructing these applicatives via a DSL.

From the documentation (emphasis mine):

Whereas a scalaz.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 (ap)


Operator |@| is the product operation

By "product operation" the OP means that it is the operation which takes two values and wraps them inside the ApplicativeBuilder.

|@| is a method that when invoked, returns an instance of ApplicativeBuilder:

final def |@|[B](fb: F[B]) = new ApplicativeBuilder[F, A, B] {
  val a: F[A] = self
  val b: F[B] = fb
}

Where F is a first order kind which has an Apply instance defined:

implicit val F: Apply[F]

Where Apply is just an Applicative without the point method.

combining your applicatives into a product by using |@| results in an ApplicativeBuilder which takes a function to perform on the product (since product + map is a very common use case)

If you we take your example and simplify it a bit for two Option[Int]s:

import scalaz.Scalaz._

val o1 = 1.some
val o2 = 1.some
val result: ApplicativeBuilder[Option, Int, Int] = o1 |@| o2
val finalRes: Option[Int] = result.apply(_ + _)

We:

  1. Apply |@| to two instances an of Option[Int] and get back an ApplicativeBuilder[Option, Int, Int]. Option here is our F, which has an instance of Apply.
  2. After getting back an instance of the builder, we invoke it's apply method. We provide it with a function of shape Int -> Int and it gives us back a Option[Int], meaning we are still inside the context, but with the operation applied to our values.
like image 183
Yuval Itzchakov Avatar answered Sep 19 '22 13:09

Yuval Itzchakov