Created
April 3, 2013 09:03
-
-
Save jnape/5299612 to your computer and use it in GitHub Desktop.
Making dealing with Future[Either[L, R]] palatable in Scala
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 com.thoughtworks.futureeither | |
import concurrent.{Await, Future} | |
import scala.concurrent.ExecutionContext.Implicits.global | |
import concurrent.duration.FiniteDuration | |
import java.util.concurrent.TimeUnit | |
class FutureEither[L, R](private val future: Future[Either[L, R]]) { | |
def flatMap[R2](block: R => FutureEither[L, R2]): FutureEither[L, R2] = { | |
val result = future.flatMap { | |
case Right(r) => block.apply(r).future | |
case Left(l) => Future.successful(Left(l)) | |
} | |
new FutureEither(result) | |
} | |
def map[R2](block: R => R2): FutureEither[L, R2] = { | |
val result = future.map { | |
case Right(r) => Right(block.apply(r)) | |
case Left(l) => Left(l) | |
} | |
new FutureEither(result) | |
} | |
def recover(block: PartialFunction[L, R]): Future[R] = { | |
future.map { | |
case Right(r) => r | |
case Left(left) => block.apply(left) | |
} | |
} | |
} | |
object FutureEither { | |
//bidirectional implicit conversions between Future[Either[L, R]] and FutureEither[L, R] | |
} | |
object Example { | |
abstract sealed class Error {} | |
case class HeadFellOff() extends Error {} | |
case class PantsFellOff() extends Error {} | |
case class WTF() extends Error {} | |
def returnString: FutureEither[Error, String] = new FutureEither(Future(Right("a string!"))) | |
def takeStringAndReturnInt(string: String): FutureEither[Error, Int] = new FutureEither(Future(Right(10))) | |
def takeIntAndReturnString(int: Int): FutureEither[Error, String] = new FutureEither(Future(Right("ftw"))) | |
def main(args: Array[String]) { | |
val result = returnString.flatMap( | |
takeStringAndReturnInt(_).flatMap( | |
takeIntAndReturnString(_).map(_.toUpperCase) | |
) | |
).recover { | |
case HeadFellOff() => "head fell off!" | |
case PantsFellOff() => "pants fell off!" | |
case unanticipated => s"$unanticipated" | |
} | |
println(Await.result(result, FiniteDuration(5, TimeUnit.SECONDS))) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment