结合F#异步也许计算前pression [英] Combine F# async and maybe computation expression

查看:114
本文介绍了结合F#异步也许计算前pression的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我想返回一个选项,而在异步工作流程:

让运行=
    异步{
        让! X = doAsyncThing
        让! Y = doNextAsyncThing点¯x
        比赛y随
        |无 - >返回None
        |一些ž - >还有些< | F Z
    }

在理想情况下,我会用从FSharpx的可能计算前pression同时为异步避免这样做的匹配。我可以做一个自定义生成器,但有一个办法一般将两个计算前pressions?它看起来是这样的:

 让运行=
    异步{
        让! X = doAsyncThing
        让! Y = doNextAsyncThing点¯x
        返回! ˚Fÿ
    }


解决方案

通常,在F#,而不是使用通用的工作流程定义手工工作流程,或使用一个已经准备好可以作为你的情况异步也许,但如果你想使用它们结合起来,你需要codeA特定的工作流程结合手。

另外,您可以使用 F#+ 是,它提供了单子通用工作流项目在这种情况下,它会自动地给你,这里有一个工作的例子,使用您的工作流程,然后使用 OptionT 这是一个单子转换:

  #nowarn3186
r组成@FsControl.dll
r组成@FSharpPlus.dll开放FSharpPlus让doAsyncThing = {异步返回System.DateTime.Now}
让doNextAsyncThing(X:System.DateTime的)= {异步
    令m = x.Millisecond
    回报(如M< 500则几μm否则无)}
令f X = 2 * X//那么你可以使用异步< _> (与你的code)
让我们来看= {单子
    让! X = doAsyncThing
    让! Y = doNextAsyncThing点¯x
    比赛y随
    |无 - >返回None
    |一些ž - >还有些< | F Z}让解析度= Async.RunSynchronously运行//或者你可以使用OptionT<异步< _>> (单子变压器)让运行'= {单子
    让! X =电梯doAsyncThing
    让! Y = OptionT(doNextAsyncThing X)
    返回˚Fÿ}让水库'=跑'|> OptionT.run |> Async.RunSynchronously

第一个功能已被解禁到另一个单子,因为它只与异步交易(不与选项),既有所以只需要'包装'变成第二个函数交易我们的 OptionT DU。

正如你可以看到这两个工作流自动导出,你有一个(异步工作流程),你想要的。

有关此方法的详细信息,请参阅单子变形金刚

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
    }

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
    }

解决方案

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.

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:

#nowarn "3186"
#r @"FsControl.dll"
#r @"FSharpPlus.dll"

open FSharpPlus

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

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.

For more information about this approach read about Monad Transformers.

这篇关于结合F#异步也许计算前pression的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆