Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stack applicative functors in Scala

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?

like image 355
kciesielski Avatar asked Apr 20 '16 18:04

kciesielski


1 Answers

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 _)
like image 88
Eric Avatar answered Nov 15 '22 06:11

Eric