9

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?

1

1 Answer 1

13

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)

3
  • I tried the (processX, processY, processZ) map { (x, y, z) => ... } but it doesn't compile for me. Is it a feature of scalaz7 to have this mapping of TupleX[Validation, ...]? Commented Aug 30, 2012 at 20:57
  • I don't think Josh was referring to scalaz at all. I'll point him to this thread.
    – Mike Slinn
    Commented Aug 31, 2012 at 5:26
  • 1
    Yeah, my post is more basic, not specific to Scalaz. I was using SBT's applicative syntax with the concepts in Scalaz. Here's a decent introductoin: github.com/bartschuller/scalaz-validation-example
    – jsuereth
    Commented Aug 31, 2012 at 14:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.