结合 F# 异步和计算表达式

编程入门 行业动态 更新时间:2024-10-22 14:41:32
本文介绍了结合 F# 异步和计算表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

假设我想在 async 工作流中返回一个 Option:

Say i want to return an Option while in an async workflow:

let run = async { let! x = doAsyncThing let! y = doNextAsyncThing x match y with | None -> return None | Some z -> return Some <| f z }

理想情况下,我会在异步的同时使用来自 FSharpx 的可能计算表达式,以避免执行 match.我可以制作一个自定义构建器,但是有没有办法将两个计算表达式一般地组合起来?它可能看起来像这样:

Ideally I would use the maybe computation expression from FSharpx at the same time as async to avoid doing the match. I could make a custom builder, but is there a way to generically combine two computation expressions? It might look something like this:

let run = async { let! x = doAsyncThing let! y = doNextAsyncThing x return! f y }

推荐答案

通常在 F# 中,您手动定义工作流而不是使用通用工作流,或者使用现成可用的工作流async 和 可能 但如果您想将它们结合使用,则需要手动编写特定的工作流组合.

Typically in F# instead of using generic workflows you define the workflow by hand, or use one that is ready available as in your case async and maybe but if you want to use them combined you will need to code a specific workflow combination by hand.

或者,您可以使用 F#+,这是一个为以下项目提供通用工作流程的项目monads,在这种情况下,它将自动为您派生,这是一个工作示例,使用您的工作流程,然后使用 OptionT 这是一个 monad 转换器:

Alternatively you can use F#+ which is a project that provides generic workflows for monads, in that case it will be automatically derived for you, here's a working example, using your workflow and then using OptionT which is a monad transformer:

#r "nuget: FSharpPlus, 1.2" open FSharpPlus open FSharpPlus.Data let doAsyncThing = async {return System.DateTime.Now} let doNextAsyncThing (x:System.DateTime) = async { let m = x.Millisecond return (if m < 500 then Some m else None)} let f x = 2 * x // then you can use Async<_> (same as your code) let run = monad { let! x = doAsyncThing let! y = doNextAsyncThing x match y with | None -> return None | Some z -> return Some <| f z} let res = Async.RunSynchronously run // or you can use OptionT<Async<_>> (monad transformer) let run' = monad { let! x = lift doAsyncThing let! y = OptionT (doNextAsyncThing x) return f y} let res' = run' |> OptionT.run |> Async.RunSynchronously

第一个函数必须被提升"到另一个 monad 中,因为它只处理 Async(而不是 Option),第二个函数处理两者它只需要打包"到我们的 OptionT DU 中.

The first function has to be 'lifted' into the other monad, because it only deals with Async (not with Option), the second function deals with both so it only needs to be 'packed' into our OptionT DU.

正如您所看到的,两个工作流都是自动派生的,一个是您拥有的(异步工作流),另一个是您想要的.

As you can see both workflows are derived automatically, the one you had (the async workflow) and the one you want.

有关此方法的更多信息,请阅读Monad Transformers.

For more information about this approach read about Monad Transformers.

更多推荐

结合 F# 异步和计算表达式

本文发布于:2023-11-17 03:09:01,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1608595.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:表达式

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!