Created
December 19, 2010 19:07
-
-
Save krasserm/747597 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scalaz._ | |
object ValidationApplicative extends Application { | |
import Scalaz._ | |
// ----------------------------------------------------------------------------------- | |
// Applicative use of scalaz.Validation to combine results of independent computations | |
// e.g. results from multiple recipients, see also multicast EIP in scalaz-camel: http://goo.gl/FXWRi | |
// ----------------------------------------------------------------------------------- | |
case class Message(b: String) { | |
def append(s: String) = Message(b + s) | |
} | |
type MessageProcessor = Message => Validation[Exception, Message] | |
def append(s: String): MessageProcessor = (m: Message) => m.append(s).success | |
def fail(msg: String): MessageProcessor = (m: Message) => (new Exception(msg)).fail | |
val lastMsg = (m1: Message) => (m2: Message) => m2 | |
// List of (independent) computations where some of them fail | |
val computations1 = List(append("-1"), fail("f1"), fail("f2"), append("-2"), append("-3")) | |
// List of (independent) computations where all succeed | |
val computations2 = List(append("-1"), append("-2"), append("-3")) | |
// Run independent computations sequentially (3x success, 2x failure) | |
val results1 = Message("a").pure[List] <*> computations1 | |
// Run independent computations sequentially (3x success) | |
val results2 = Message("a").pure[List] <*> computations2 | |
{ | |
// Makes Exception an instance of Semigroup type class (select first exception) | |
implicit def ExceptionSemigroup: Semigroup[Exception] = semigroup((e1, e2) => e1) | |
// combine Validation results in list via foldLeft | |
println(results1.tail.foldLeft(results1.head) { (z, m) => m <*> z ∘ lastMsg }) // Failure(java.lang.Exception: f1) | |
println(results2.tail.foldLeft(results2.head) { (z, m) => m <*> z ∘ lastMsg }) // Success(Message(a-3)) | |
// Alternative | |
results1.sequence[PartialApply1Of2[Validation, Exception]#Apply, Message] match { | |
case Success(l) => println(l.last.success) | |
case Failure(e) => println(e.fail) // Failure(java.lang.Exception: f1) | |
} | |
results2.sequence[PartialApply1Of2[Validation, Exception]#Apply, Message] match { | |
case Success(l) => println(l.last.success) // Success(Message(a-3)) | |
case Failure(e) => println(e.fail) | |
} | |
} | |
{ | |
// Makes Exception an instance of Semigroup type class (select second exception) | |
implicit def ExceptionSemigroup: Semigroup[Exception] = semigroup((e1, e2) => e2) | |
// combine Validation results in list via foldLeft | |
println(results1.tail.foldLeft(results1.head) { (z, m) => m <*> z ∘ lastMsg }) // Failure(java.lang.Exception: f2) | |
println(results2.tail.foldLeft(results2.head) { (z, m) => m <*> z ∘ lastMsg }) // Success(Message(a-3)) | |
} | |
} |
Thanks for the pointer, Jason. Updated the example again.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Take a look at
MA#sequence
, allowingList[Validation[A, B]] => Validation[A, List[B]]
, givenA: Semigroup
.