Skip to content

Instantly share code, notes, and snippets.

@OlivierBlanvillain
Created April 21, 2016 09:42
Show Gist options
  • Save OlivierBlanvillain/48e0dedcec5f79d93cce6c00e311df96 to your computer and use it in GitHub Desktop.
Save OlivierBlanvillain/48e0dedcec5f79d93cce6c00e311df96 to your computer and use it in GitHub Desktop.
// Needed to make it work with Future, we could use any Functor instead.
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import scalaz.std.scalaFuture._
trait T
trait A
trait B
object DemoOptionT {
def `We want to combine two values wrapped into Future[Option[_]]` = {
val foa: Future[Option[A]] = ???
val fob: Future[Option[B]] = ???
def ab2t(a: A, b: B): T = ???
val output: Future[Option[T]] =
for {
oa <- foa
ob <- fob
} yield for {
a <- oa
b <- ob
} yield ab2t(a, b)
// Using Monad transformers:
import scalaz.OptionT._
val output2: Future[Option[T]] =
(
for {
a <- optionT(foa)
b <- optionT(fob)
} yield ab2t(a, b)
).run
}
def `A more tricky example where the second value is a function of the first` = {
val foa: Future[Option[A]] = ???
def a2fot(a: A): Future[Option[T]] = ???
val output: Future[Option[T]] =
for {
oa <- foa
t <- oa match {
case None => Future(None)
case Some(a) => a2fot(a)
}
} yield t
// Using Monad transformers:
import scalaz.OptionT._
val output2: Future[Option[T]] =
(
for {
a <- optionT(foa)
t <- optionT(a2fot(a))
} yield t
).run
}
}
@OlivierBlanvillain
Copy link
Author

Note that in the first example we don't actually need all the power of Monad transformers since we are combining values in a applicative style. Since Applicatives are closed under products and composition something like the following could be used instead:

implicit foAp: Applicative[Future[Option[?]]] =
  implicitly[Applicative[Future]].compose(implicitly[Applicative[Option]])

(foa |@| fob).map(ab2t)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment