[英]Combine Async and Option monads
最近,在編寫一些可用於許多嵌套異步工作流的代碼時,我發現了一種新興的模式,這種模式對我來說很香。 一個簡單的例子:
let flip f x y = f y x
let slowInc x = async {
do! Async.Sleep 500
printfn "Here you go, %d" x
}
let verboseFun inp = async {
match List.tryFind (flip (>) 3) inp with
| Some x -> do! slowInc x
| _ -> ()
}
verboseFun [1..5] |> Async.RunSynchronously
對我來說,“ verboseFun”似乎很冗長,但我想不出一種將Option和Async monad結合起來的方法,因此可以在不進行模式匹配的情況下將其重寫。 我在想類似
let terseFun inp = async {
inp
|> List.tryFind (flip (>) 3)
|> Option.iterAsync slowInc
}
在我看來,很可能我不知道有什么構建塊可以實現這一目標。
編輯:托馬斯回答后的額外澄清。
如果所有事情都是同步的,我試圖調整對我來說微不足道的東西,例如,
let terseFun inp =
inp
|> List.tryFind (flip (>) 3)
|> Option.iter someSideEffectFunciton
成為嵌套異步工作流程的一部分。 最初我在想“只是去做!在這里”
let terseFun inp = async {
inp
|> List.tryFind (flip (>) 3)
|> Option.iter (fun x -> async { do! someSideEffectFunciton x })
|> ignore
}
但這立刻讓我感到不對勁,因為VS開始要求忽略。 希望這有助於澄清。
ExtCore庫具有一堆幫助函數,可讓您處理返回可選值(即Async<'T option>
類型)的Async<'T option>
計算,甚至定義asyncMaybe
計算生成器以使用它們。
我沒有廣泛使用它,但是從我做過的一些簡單實驗來看,它似乎並沒有像它可能與F#的其余async
功能很好地集成在一起,但是如果您朝這個方向發展,ExtCore是可能是周圍最好的圖書館。
以下是使用AsyncMaybe.Array
的iter
函數( 源在此處 )。 這有點丑陋,因為我必須使slowInc
的類型為Async<unit option>
,但它與您的要求非常接近:
let slowInc x = async {
do! Async.Sleep 500
printfn "Here you go, %d" x
return Some ()
}
let verboseFun inp =
inp
|> List.tryFind (fun x -> 3 > x)
|> Array.ofSeq
|> AsyncMaybe.Array.iter slowInc
|> Async.Ignore
另外,我還刪除了您的flip
功能,因為在F#中通常不建議使用這種樣式(它會使代碼變得晦澀難懂)。
就是說,我認為您實際上並不需要整個ExtCore庫。 僅從發布的一個示例很難看出您的一般模式是什么,但是如果所有代碼段看起來都與發布的示例相似,則可以定義自己的asyncIter
函數,然后在其他地方使用它:
let asyncIter f inp = async {
match inp with
| None -> ()
| Some v -> do! f v }
let verboseFun inp =
inp
|> List.tryFind (fun x -> x > 3)
|> asyncIter slowInc
關於F#的偉大之處在於,自己編寫這些抽象並使它們完全符合您的需求非常容易:-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.