26

アプリカティブ ファンクターは、計算ステップが独立している場合に、モナドの代替としてよく言及されます。F[G[X]]よく言及される利点の 1 つは、常にアプリカティブでもあるため、アプリカティブをスタックする場合にトランスフォーマーが必要ないことです。次の機能があるとしましょう:

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

Future[Option[User]]andを取得し、それFuture[Option[Data]]を でマップするために、エレガントなスタッキングが必要processです。

これまでのところ、私はこれを思いつきました(猫を使用):

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 に答える