簡體   English   中英

用慣用的方式鏈接期貨和期權

[英]Chaining futures and options idiomatically

def foo(user, id): Future[Option[Bar]] =
  bar(user, id).map(_.map(_.address.flatMap(_.street)))
    .flatMap {
      case Some(street) =>
        baz(user, street).flatMap(_ => get(id))
      case None => successful(None)
    }

函數欄返回一個Option[UserInfo] ,然后我將其映射到UserInfo Address也是一個Option所以我flatMap可以訪問street 然后,如果有一條街道,我想打電話給baz ,如果沒有,那么None 忽略業務邏輯,它就是為了這個例子。

這里的代碼存在問題,因為它無法編譯。

Some(street)是一個Option ,因為第3行上的flatMap是在第一個_而不是_.address上映射的結果上_.address

雖然我可以通過一些括號雜耍等來使用它,但這段代碼開始變得難以閱讀和推理。

理解是答案嗎?

PS:這個例子中可能缺少某些類型信息,所以請問我會詳細說明。

編輯:

case class UserInfo(id: UserId, address: Option[Address])

case class Address(street: Option[List[Street]], state: Option[State])

如果我理解方法簽名是正確的:

 def bar(user, id): Option[UserInfo]
 def baz(user, List[Street]): Future[BarId]
 def get(id): Option[Bar]

你可以實現這樣的方法:

val streetsOpt: Option[List[Street]] = bar(user, id).flatMap(_.flatMap(_.address.flatMap(_.street)))

streetsOpt.flatMap(streets => {
    baz(user, streets).map(_ => get(id))
}).getOrElse(successful(None)))

在這一行中快速查看此內容:

baz(user, street).flatMap(_ => get(id))

我不認為最后一個flatMap不會正常工作,因為你似乎傳遞的函數類似於:

f: => A

即從某個上下文中提取底層值,而flatMap希望您解壓縮該值然后換行新的上下文,因此類型為:

f: A => M[B]

當你打電話給

get(id)

不應該將它應用於map方法,而是期望類型的函數:

f: A => B

有兩種方法可以處理像這樣的嵌套上下文。 我講了三個我知道的內容:monad變換器(顯式,更“標准”,但更冗長),Kleisli(非常優雅,如果你願意用無點樣式編寫),或者我的scalaz-transfigure庫(有點不成熟,有點不那么明確,但非常簡潔)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM