如何在 Scala 中堆叠应用函子
How to stack applicative functors in Scala
当您的计算步骤是独立的时,应用函子经常被提及作为 monad 的替代品。他们经常提到的优点之一是当你想堆叠应用程序时不需要转换器,因为 F[G[X]]
总是也是一个应用程序。
假设我有以下功能:
def getDataOption(): Option[Data]
def getUserFuture(): Future[User]
def process(data: Data, user: User)
我想要优雅的堆叠以获得 Future[Option[User]]
和 Future[Option[Data]]
并将其映射到 process
.
到目前为止我只想到了这个(使用猫):
Applicative[Future]
.compose[Option]
.map2(
Applicative[Future].pure(getDataOption()),
getUserFuture().map(Applicative[Option].pure))(process)
但我确信这远非理想。有没有更优雅和通用的方法来实现同样的目标?
这里最难的是类型推断。这是我能做的最好的了
// 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 _)
当您的计算步骤是独立的时,应用函子经常被提及作为 monad 的替代品。他们经常提到的优点之一是当你想堆叠应用程序时不需要转换器,因为 F[G[X]]
总是也是一个应用程序。
假设我有以下功能:
def getDataOption(): Option[Data]
def getUserFuture(): Future[User]
def process(data: Data, user: User)
我想要优雅的堆叠以获得 Future[Option[User]]
和 Future[Option[Data]]
并将其映射到 process
.
到目前为止我只想到了这个(使用猫):
Applicative[Future]
.compose[Option]
.map2(
Applicative[Future].pure(getDataOption()),
getUserFuture().map(Applicative[Option].pure))(process)
但我确信这远非理想。有没有更优雅和通用的方法来实现同样的目标?
这里最难的是类型推断。这是我能做的最好的了
// 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 _)