Created
January 21, 2013 21:28
-
-
Save drstevens/4589599 to your computer and use it in GitHub Desktop.
Define Apply[Future] in order to sequence. Written for Akka 1.3.1 (old, I know) and Scalaz 6.0.4. I imagine similar could be written for Akka 2.1.x and Scalaz 7. I've used this in many places so far without issue, but I've only used it for sequencing through something like `Validation[S, Future[Validation[S, Future[B]]]`. If I'm breaking some la…
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
object FuturePimps { | |
/** | |
* Use this instead of new AlreadyCompletedFuture[T] to prevent accidental use of default Akka timeout | |
**/ | |
def alreadyCompletedFuture[T](v: T)(implicit timeout: Timeout): AlreadyCompletedFuture[T] = | |
new AlreadyCompletedFuture[T](Right(v), timeout.duration.toMillis) | |
class FutureFuture[T](f: () => Future[Future[T]]) { | |
def flatten: Future[T] = f().flatMap(identity) | |
} | |
implicit def `pimpMyFuture^2`[T](f: => Future[Future[T]]) = new FutureFuture(() => f) | |
object TypeClasses { | |
implicit def FutureBind = new Bind[Future] { | |
def bind[A, B](a: Future[A], f: A => Future[B]) = a flatMap f | |
} | |
implicit def FutureFunctor: Functor[Future] = new Functor[Future] { | |
def fmap[A, B](r: Future[A], f: A => B) = r map f | |
} | |
/** | |
* NOTE: In order to use this, a timeout must be implicitly in scope at call site!!! | |
* If no timeout is in scope, type checker will likely fail with error about missing Applicative | |
*/ | |
implicit def FuturePure(implicit timeout: Timeout): Pure[Future] = new Pure[Future] { | |
def pure[A](a: => A) = alreadyCompletedFuture(a) | |
} | |
implicit def FutureApply[S]: Apply[Future] = FunctorBindApply[Future] | |
} | |
} | |
import FuturePimps._ | |
import FuturePimps.TypeClasses._ | |
implicit val timeout: ActorTimeout = Duration(10, TimeUnit.SECONDS) | |
val expectedSuccess = 5 | |
val successOfFuture: Validation[String, Future[Int]] = alreadyCompletedFuture(5).success | |
val futureOfSuccess = successOfFuture.sequence | |
futureOfSuccess.get assert_=== expectedSuccess.success | |
val expectedFailure = "Failed!!!" | |
val failureOfFuture: Validation[String, Future[Int]] = expectedFailure.fail | |
val futureOfFailure = failureOfFuture.sequence | |
futureOfFailure.get assert_=== expectedFailure.fail | |
val expectedOptionValue = 5 | |
val optionOfFuture: Option[Future[Int]] = alreadyCompletedFuture(5).some | |
val futureOfOption = optionOfFuture.sequence | |
futureOfOption.get assert_=== expectedOptionValue.some |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment