【问题标题】:Flatten long nesting of Monadic types in Scala在 Scala 中扁平化 Monadic 类型的长嵌套
【发布时间】:2015-11-11 11:30:42
【问题描述】:

我有一个函数可以在给定 JobIds 的情况下获取一系列 workItemIds,并带有以下签名 -

def getWorkItemIds(jobId: JobId): Future[Seq[WorkItemId]]

我有另一个函数,它给定一个 WorkItemId 将返回一个 workItem。带签名 -

def getWorkItem(workItemId: WorkItemId): Future[Option[WorkItem]]

现在我正在尝试编写一个函数,它使用这两个函数返回给定 JobId 的 WorkItem 序列,如下所示 -

  def getWorkItemsForJob(jobId: JobId): Future[Seq[Future[Option[WorkItem]]]] = {
val workItemIds: Future[Seq[WorkItemId]] = getWorkItemIds(jobId)

   val res = workItemIds.map {
     idSeq => idSeq.map {
       id => getWorkItem(id)
     }
   }
   res
}

问题是返回类型,我不想返回这种可怕的类型,而是应该返回像Future[Seq[WorkItem]] 这样更简单的东西。现在我可以把它弄平了 -

  def getWorkItemsForJob(jobId: JobId): Future[Seq[WorkItem]] = {
val workItemIds: Future[Seq[WorkItemId]] = getWorkItemIds(jobId)

  val res = workItemIds.map {
    idSeq => idSeq.flatMap {
      id => getWorkItem(id).get
    }
  }
  res
}

这为我提供了我想要的正确的Future[Seq[WorkItem]] 类型,但它要求我对未来有所了解,这感觉不正确。我也可以使用 await ,但这将是一个阻塞调用。有没有办法在不阻塞的情况下展平上述类型?

【问题讨论】:

    标签: scala monads


    【解决方案1】:

    你要找的是Future.traverse:

    def getWorkItemsForJob(jobId: JobId): Future[Seq[WorkItem]] =
      getWorkItemIds(jobId).flatMap(Future.traverse(_)(getWorkItem).map(_.flatten)) 
    

    .traverse 调用从getWorkItemIds 调用中获取Seq,并返回对每个条目调用getWorkItem 的结果的Future[Seq],没有内部Future 包装。

    接近末尾的.map(_.flatten) 将内部Seq[Option[WorkItem]] 扁平化为Seq[WorkItem]

    【讨论】:

      【解决方案2】:

      你可以这样做:

      def getWorkItemsForJob(jobId: JobId): Future[Seq[WorkItem]] = 
        for (
          seq <- getWorkItemIds(jobId);
          list <- Future.traverse(seq)(getWorkItem)
        ) yield list.flatten
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-19
        • 1970-01-01
        • 1970-01-01
        • 2018-07-17
        • 2017-12-01
        • 2017-11-27
        • 2014-08-12
        相关资源
        最近更新 更多