scala - 以功能方式进行多个 API 调用

标签 scala functional-programming category-theory scala-cats

通过使用 Scala 和 Cats(或者可能是另一个专注于类别理论和/或函数式编程的库)以最具功能性(代数)的方式解决这个问题的最佳方法是什么?
资源
如果我们有以下方法来执行 REST API 调用来检索单条信息?

type FutureApiCallResult[A] = Future[Either[String, Option[A]]]

def getNameApiCall(id: Int): FutureApiCallResult[String]
def getAgeApiCall(id: Int): FutureApiCallResult[Int]
def getEmailApiCall(id: Int): FutureApiCallResult[String]
如您所见,它们产生异步结果。在 API 调用期间,Either monad 用于返回可能的错误,而 Option 用于在 API 未找到资源时返回 None(这种情况不是错误,而是可能的和所需的结果类型)。
以功能方式实现的方法
case class Person(name: String, age: Int, email: String)

def getPerson(id: Int): Future[Option[Person]] = ???
如果任何 API 调用失败或任何 API 调用返回 None(无法组合整个 Person 实体),则此方法应使用上面定义的三个 API 调用方法异步组合并返回 Person 或 None
要求
出于性能原因,所有 API 调用都必须以并行方式完成
我猜
我认为最好的选择是使用 Cats Semigroupal 已验证 但是当我试图处理 Future 和这么多嵌套的 Monad 时我迷路了 :S
谁能告诉我您将如何实现这一点(即使更改方法签名或主要概念)或将我指向正确的资源?我对 Cats 和 Algebra 在编码方面很陌生,但我想学习如何处理这种情况,以便我可以在工作中使用它。

最佳答案

这里的关键要求是它必须并行完成。这意味着使用 monad 的明显解决方案已经过时,因为 monadic bind 是阻塞的(它需要结果,以防它必须在其上进行分支)。所以最好的选择是使用 applicative。

我不是 Scala 程序员,所以我无法向您展示代码,但这个想法是应用仿函数可以提升多个参数的函数(常规仿函数使用 map 提升单个参数的函数)。在这里,您将使用类似 map3 的内容。解除 Person 的三参数构造函数工作在三个 FutureResult s。搜索“Scala 中的应用程序 future ”会返回一些点击。 Either也有应用实例和 Option而且,与 monad 不同,应用程序可以很容易地组合在一起。希望这可以帮助。

关于scala - 以功能方式进行多个 API 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48138007/

相关文章:

javascript - Lodash Flow 和 TypeScript

scala - Tuple2 的概念目的是什么?

functional-programming - Erlang 如何存储大数?

scala - 如何避免 Spark (2.4) SQL 中 ArrayType 的自动转换 - Scala 2.11

Scala 案例类 : avoid recomputation of the property

haskell - Haskell中扩展类型类的含义是什么?

haskell - 双胞胎的方法是什么?

haskell - 这些类似 Free 的结构有一个概括吗?

scala - Spark数据帧-按键减少

scala - 在 Databricks 上使用 Scala Spark 加载 Z 压缩文件