[英]F# async and anonymous functions
我有一個用這個簽名做一些 IO 的方法:
member this.IsRestaurantInCategoryAsync(restaurantName: string, restaurantAddress: string, restaurantCategory: string) =
async { ///long running methods }
我想像這樣在匿名函數中調用它:
this.GetRestaurants()
|> Seq.filter(fun (name, address) -> categoryRepository.IsRestaurantInCategoryAsync(name, address, category))
|> Seq.toList
問題是 IsRestaurantInCategoryAsync 返回async<bool>
,而不是bool
。 我如何讓Seq.Filter
處理它?
我應該使用 let 將async<bool>
轉換為bool
嗎? 那么我必須編寫一個非匿名函數來分配回報嗎?
您可以使用Async.RunSynchronously
同步運行操作 - 但這會破壞使用異步工作流來避免編寫阻塞代碼的意義,因此這不是正確的方法!
有不同的方法可以做到這一點 - 您可以按順序遍歷所有餐廳(將一個一個處理),或者您可以並行運行過濾(它將使用 .NET 認為好的線程池線程)。
並行版本如下所示:
let checkAll = async {
let! all =
[ for r in this.GetRestaurants() -> async {
let! include = catagoryRepository.IsRestaurantInCatagoryAsync(name, address,catagory)
if include then return Some(r) else return None } ]
|> Async.Parallel
let included = Seq.choose id all
printfn "%A" included }
請注意,代碼都在async
塊內(因為這使它保持異步)。 它首先創建一個計算列表,返回帶有None
(跳過餐廳)或Some
(包括餐廳)的選項,然后運行所有選項並使用Seq.choose
過濾None
值。
要按順序實現這一點,您基本上需要自己的過濾器實現,該filter
包含在async
塊中。 這將是一個很好的起點(盡管它不是尾遞歸的):
let rec filterAsync f items = async {
match items with
| [] -> return []
| x::xs ->
let! included = f x
let! rest = filterAsync f xs
return (if included then x::rest else rest) }
this.GetRestaurants()
|> AsyncSeq.filterAsync categoryRepository.IsRestaurantInCategoryAsync name address category
|> AsyncSeq.toListAsync
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.