【问题标题】:Combine Async and Option monads结合 Async 和 Option monad
【发布时间】:2014-08-08 15:44:58
【问题描述】:

最近在编写一些适用于许多嵌套异步工作流程的代码时,我发现了一种新出现的模式,让我觉得很奇怪。一个简单的例子:

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 开始要求忽略。 希望这有助于澄清。

【问题讨论】:

标签: asynchronous f# monads monad-transformers async-workflow


【解决方案1】:

ExtCore library 有一堆帮助函数,可让您处理返回可选值的异步计算,即 Async<'T option> 类型,它甚至定义了 asyncMaybe 计算构建器来处理它们。

我没有广泛使用它,但从我做的一些简单实验来看,它似乎没有像它可能的那样与 F# 的 async 功能的其余部分很好地集成,但如果你想进去在这个方向上,ExtCore 可能是最好的库。

以下使用来自AsyncMaybe.Array (source is here) 的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 库。仅从您发布的一个示例中很难看出您的一般模式是什么,但如果您的所有代码 sn-ps 看起来都与您发布的代码相似,您可以定义自己的 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# 的伟大之处在于,您可以很容易地自己编写这些抽象并使它们完全符合您的需求:-)

【讨论】:

    猜你喜欢
    • 2021-07-30
    • 2011-05-07
    • 1970-01-01
    • 2017-12-06
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 2014-03-22
    • 2015-05-21
    相关资源
    最近更新 更多