26

当您的计算步骤是独立的时,应用函子经常被提及作为 monad 的替代品。它们经常提到的一个优点是,当你想要堆叠应用程序时不需要转换器,因为F[G[X]]它始终也是一个应用程序。假设我有以下功能:

def getDataOption(): Option[Data]
def getUserFuture(): Future[User]
def process(data: Data, user: User)

我想要优雅的堆叠以获得Future[Option[User]]andFuture[Option[Data]]并用process.

到目前为止,我只想到了这个(使用 Cats):

Applicative[Future]
  .compose[Option]
    .map2(
      Applicative[Future].pure(getDataOption()),
      getUserFuture().map(Applicative[Option].pure))(process)

但我敢肯定这远非理想。有没有更优雅和通用的方法来实现同样的目标?

4

1 回答 1

3

这里最困难的是类型推断。这是我能做的最好的

  // 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 _)
于 2016-04-21T07:11:05.473 回答