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
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