Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do applicative functors tie in with parallelizing algorithms? (Scala and Scalaz)

From Josh Suereth's "Scala in Depth":

"Applicative functors provide a way to take two computations and join them together using a function. The Traversable example highlights how two collections can be parallelized into pairs. Applicative functors and parallel processing go together like bread and butter."

I have a vague idea of the whole functors/monads/applicative stuff, but not exactly a strong grasp of it (new to the whole monad, functor stuff). I understand a bit of the concept of monads (flatten, flatMap) and monadic workflow, and functors (maps).

Can anyone please elaborate for me in terms of how it's done, examples, and/or benefits of it versus "traditional" parallelization?

like image 807
adelbertc Avatar asked Aug 29 '12 18:08

adelbertc


People also ask

What is applicative in Scala?

Applicative is a generalization of Monad , allowing expression of effectful computations in a pure functional way. Applicative is generally preferred to Monad when the structure of a computation is fixed a priori. That makes it possible to perform certain kinds of static analysis on applicative values.

Could you comfortably explain the difference between a monad and an applicative functor?

Functors apply a function to a wrapped value: Applicatives apply a wrapped function to a wrapped value: Monads apply a function that returns a wrapped value to a wrapped value. Monads have a function >>= (pronounced "bind") to do this.

What are functors and monads?

A functor takes a pure function (and a functorial value) whereas a monad takes a Kleisli arrow, i.e. a function that returns a monad (and a monadic value). Hence you can chain two monads and the second monad can depend on the result of the previous one.


1 Answers

I forwarded the question to Josh Suereth. This is his reply:

Mike -

I don't have a lot of time to respond, but I'll offer to examples of what I mean:

Example #1 - Form Validation.

I want to run some validation against input and aggregate all the errors, i.e. detect them in parallel. With applicative functions I can do so.

So, given a set of "processing" functions, like so:

def processUser(data: Data): Validation[User] = {
  if (data get "username" isEmpty) Failure("username must not be empty")
  else {  
     val Some(user) = data get "username"
     if (user contains badCharacterRegex) Failure(s"username must not contain one of ${badchars}")
     else Success(user)
  }
}
def processCreditCard(data: Data): Validation[CreditCard] = ...
def processAddress(data: Data): Validation[Address] = ...

def handleForm(data: Data): ??? = {
  (processUser(data), processCreditCard(data), processAddress(data)) map { (user, card, address) =>
    postPayment(user, address, card)
  } recover {   (errors) =>
     errors foreach println
  } 

Now handle form will print out errors with CreditCard/username + address all at the same time, since you've combined them using an applicative functor. That's parallel error reporting (although testing isn't actually done in parallel).

(2) Futures

I want to do a few things in parallel and combine results. Future's "zip" method is actually an applicative functor in disguise. I can do this:

Future(computation1) zip Future(computation2) map { case (one,two) => .... }

I've just used Applicative Functors to "join" parallel computations.
It's exactly the same as the Form validation example.

Hope that helps! - Josh

(note these code snippets are non-compilable examples; I was using SBT's applicative syntax with the concepts in Scalaz, so you need to choose a library to use applicatives and what they are applying onto)

like image 178
Mike Slinn Avatar answered Oct 18 '22 06:10

Mike Slinn