Skip to main content
improve formatting
Source Link
jub0bs
  • 64.5k
  • 26
  • 191
  • 193

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

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
add note about how the code is generic and not actually compilable as-is
Source Link

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)

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

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)

Source Link
Mike Slinn
  • 8.3k
  • 7
  • 54
  • 89

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