Created
June 27, 2012 18:03
-
-
Save robinp/3005729 to your computer and use it in GitHub Desktop.
Akka Future Applicative typeclass for scalaz-seven
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
package akkaz | |
import akka.actor._ | |
import akka.util.duration._ | |
import akka.util.Timeout | |
import akka.dispatch.{ExecutionContext, Future} | |
object Futureapplicative extends App { | |
val system = ActorSystem("Futureapplicative") | |
implicit val timeout = Timeout(5 seconds) | |
implicit val dispatcher = ExecutionContext.defaultExecutionContext(system) | |
// | |
// Without scalaz | |
// | |
///////// CODE | |
private def funcReturnEither(x: Int): Either[Exception, Int] = Right(x * 2) | |
private def funcReturnEither2(x: Int): Either[Exception, Int] = Right(x - 1) | |
val f1: Future[Either[Exception, Int]] = Future { Right(1) } | |
val f2: Future[Either[Exception, Int]] = f1 flatMap { maybeX => Future { maybeX.right.flatMap(funcReturnEither) } } | |
val f3: Future[Either[Exception, Int]] = f2 flatMap { maybeX => Future { maybeX.right.flatMap(funcReturnEither) } } | |
val f4: Future[Either[Exception, Int]] = f1 flatMap { maybeX => Future { maybeX.right.flatMap(funcReturnEither2) } } | |
val res: Future[Either[Exception, (Int, Int, Int, Int)]] = | |
for { | |
r1 <- f1 | |
r2 <- f2 | |
r3 <- f3 | |
r4 <- f4 | |
} yield { | |
for { | |
x <- r1.right | |
y <- r2.right | |
z <- r3.right | |
w <- r4.right | |
} yield (x, y, z, w) | |
} | |
res.foreach(println) | |
////////// END | |
// | |
// With scalaz | |
// | |
import scalaz._ | |
import Scalaz._ | |
// Some typeclass for Future | |
trait FutureFunctor extends Functor[Future] { | |
override def map[A, B](fa: Future[A])(f: (A) => B) = | |
fa.map(f) | |
} | |
trait FutureApply extends Apply[Future] { | |
override def ap[A, B](fa: => Future[A])(f: => Future[(A) => B]): Future[B] = | |
fa.zip(f).map{case (a, f) => f(a)} | |
} | |
trait FuturePointed extends Pointed[Future] { | |
override def point[A](a: => A) = Future { a } | |
} | |
object FutureApplicative extends Applicative[Future] with FutureFunctor with FutureApply with FuturePointed | |
// The composed applicative | |
implicit val futureValidatedApplicative2: Applicative[({type l[x] = Future[ValidationNEL[Exception, x]]})#l] = | |
FutureApplicative.compose[({type l[x] = ValidationNEL[Exception, x]})#l] | |
// some typedefs for convenient usage | |
type Validated[A] = ValidationNEL[Exception, A] | |
type FutureValidated[A] = Future[Validated[A]] | |
//////// CODE | |
private def funcReturnValidation(x: Int): Validated[Int] = (x * 2).successNel | |
private def funcReturnValidation2(x: Int): Validated[Int] = (x - 1).successNel | |
val g1: FutureValidated[Int] = Future { 1.successNel } | |
val g2: FutureValidated[Int] = g1 flatMap { maybeX => Future { maybeX.flatMap(funcReturnValidation) } } | |
val g3: FutureValidated[Int] = g2 flatMap { maybeX => Future { maybeX.flatMap(funcReturnValidation) } } | |
val g4: FutureValidated[Int] = g1 flatMap { maybeX => Future { maybeX.flatMap(funcReturnValidation2) } } | |
val res2: FutureValidated[(Int, Int, Int, Int)] = (g1 <****> (g2, g3, g4))((_, _, _, _)) | |
res2.foreach(println) | |
//////// END | |
// the following doesn't typecheck due to SI-2712 | |
// val y = ((Future(2.successNel[Exception])) |@| Future(22.successNel[Exception]))(_ + _) | |
// but this passes | |
// val g1: FutureValidated[Int] = Future(2.successNel) | |
// val g2: FutureValidated[Int] = Future(3.successNel) | |
// val x = (g1 |@| g2)(_ + _) | |
system.shutdown() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment