Applicative functors are often mentioned as an alternative to monads when your computation steps are independent. One of their often-mentioned advantages is that you don't need transformers when you want to stack applicatives, because F[G[X]] is always also an applicative.
Let's say I have following functions:
def getDataOption(): Option[Data]
def getUserFuture(): Future[User]
def process(data: Data, user: User)
I would like to have elegant stacking in order to get a Future[Option[User]] and Future[Option[Data]] and map that with process.
So far I only came up with this (using Cats):
Applicative[Future]
  .compose[Option]
    .map2(
      Applicative[Future].pure(getDataOption()),
      getUserFuture().map(Applicative[Option].pure))(process)
but I'm sure it's far from ideal. Is there a more elegant and generic way to achieve the same?
The most difficult thing is type inference here. This is the best I could do
  // for the Applicative[Future[Option[?]]
  import cats.Applicative
  implicit val fo = {
    import cats.std.future._
    import cats.std.option._
    Applicative[Future].compose[Option]
  }
  // for the |@| syntax
  import cats.syntax.cartesian._
  // to guide type inference
  type FutureOption[A] = Future[Option[A]]
  ((Future(getDataOption): FutureOption[Data]) |@|
    getUserFuture.map(Option.apply)).map(process _)
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With