David Portabella
David Portabella

Reputation: 12720

how to transform Future[Option[(Person, Future[Vector[Order]])]] into Future[Option[(Person, Vector[Order])]]

I currently have this:

def maybePerson(id: Int): Future[Option[Person]] = ???
def orders(personId : Int): Future[Vector[Order]] = ???

val maybePersonAndOrders: Future[Option[(Person, Future[Vector[Order]])]] =
  maybePerson(is = 10).map(_.map { person =>
    (person, orders(person.id))
  })

How can I transform it into (merge the two futurs into one):

val maybePersonAndOrders: Future[Option[(Person, Vector[Order])]] = ???

Upvotes: 1

Views: 46

Answers (1)

Mario Galic
Mario Galic

Reputation: 48420

Consider OptionT monad transformer

(for {
  person <- OptionT(maybePerson(42))
  orders <- OptionT.liftF(orders(person.id))
} yield {
  (person, orders)
}).value

Here is a working example

import cats.data.OptionT
import cats.implicits._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

object OptionTExample extends App {

  case class Person(id: Int, name: String)
  case class Order(personId: Int)

  def maybePerson(id: Int): Future[Option[Person]] = Future(Some(Person(42, "picard")))
  def orders(personId : Int): Future[Vector[Order]] = Future(Vector(Order(personId)))

  val maybePersonAndOrders: Future[Option[(Person, Vector[Order])]] = {
    (for {
      person <- OptionT(maybePerson(42))
      orders <- OptionT.liftF(orders(person.id))
    } yield {
      (person, orders)
    }).value
  }

  maybePersonAndOrders.map(println)
  Thread.sleep(1000)
}

which outputs

Some((Person(42,picard),Vector(Order(42))))

Upvotes: 3

Related Questions