Skip to content

Instantly share code, notes, and snippets.

@miguel-vila
Last active December 25, 2015 06:09
Show Gist options
  • Save miguel-vila/6929747 to your computer and use it in GitHub Desktop.
Save miguel-vila/6929747 to your computer and use it in GitHub Desktop.
The setup: four types A,B, C and D, an initial value x of the type Future[Option[A]] and three functions: f1: A => Option[B] , f2: B => Future[Option[C]] and f3: C => D. How can you write a for comprehension starting with x that results in a value of the type Future[Option[D]] that would be the "composition" of the three functions? (thanks to Huw:
import scalaz.contrib.std.FutureInstances // Dependency: scalaz-contrib
import scalaz.{ Monad , OptionT } // Dependency: scalaz
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
class FutureAndOptionComposition[A, B, C, D]
extends FutureInstances
// The FutureInstances trait has a method which creates a Monad instance
// for Future which is used implicitly by the OptionT
{
val x: Future[Option[A]] = ???
def f1: A => Option[B] = ???
def f2: B => Future[Option[C]] = ???
def f3: C => D = ???
val result: Future[Option[D]] = (for {
a <- OptionT(x)
b <- OptionT(Future.successful(f1(a))) // Alternatively using scalaz Option (import scalaz.std.option._) this could be rewritten as b <- OptionT( f1(a).point[Future] )
c <- OptionT(f2(b))
} yield f3(c)).run
//To make it look smoother:
import scala.language.implicitConversions
implicit def conversion[X](optt: OptionT[Future,X]): Future[Option[X]] = optt.run
val result2: Future[Option[D]] = for {
a <- OptionT(x)
b <- OptionT(Future.successful(f1(a)))
c <- OptionT(f2(b))
} yield f3(c)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment