如何在F#的面向铁路的程序中从错误跟踪切换回成功跟踪? [英] How to switch from error track back to success track in railway-oriented program in F#?

查看:49
本文介绍了如何在F#的面向铁路的程序中从错误跟踪切换回成功跟踪?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Scott Wlashin的AsyncResult,想知道如何从错误轨道更改为成功轨道.

Using AsyncResult from Scott Wlashin and wondering how I can change from the error track to the success track.

伪代码:

let orchestratorFunction() : AsyncResult<Customer, CustomerError> = asyncResult {

   let! output1 = callFunction1 arg1 arg2 |> AsyncResult.MapError CustomerError.Val1

   let! output2 = callFunction2 arg1 arg2 |> AsyncResult.MapError CustomerError.Val2

   let! output3 = callFunction3 arg1 arg2 |> AsyncResult.MapError (fun e -> ********HERE I WANT TO GET BACK TO THE SUCCESS PATH AND RETURN output3*********)

}

or a more realistic example: 

let createCustomer() : AsyncResult<Customer, CustomerError> = asyncResult {

   let! customerDto = mapDtoFromHttpRequest arg1 arg2 |> AsyncResult.MapError CustomerError.Val1

   let! validatedCustomer = validateCustomer arg1 arg2 |> AsyncResult.MapError CustomerError.Val2

   let! validatedCustomer = insertCustomer arg1 arg2 
      |> AsyncResult.MapError (fun e -> 
            match e with 
            | DuplicateCustomer _ -> 
                loadCustomerById xx 
                |> (fun c -> 
                      if c.LastCausationId = validatedCustomer.LastCausationId 
then c 
else e))
}

因此,基本上,我试图摆脱不愉快的道路,因为这是幂等的REST操作,任何重复的请求都将以200 OK进行回答,就好像它们是原始请求一样,以便客户端可以拥有一个简单的请求.逻辑.

So basically I am trying to get out of the unhappy path, because this is an idempotent REST operation and any repetitive requests will be answered with 200 OK, as if they were the original request, so that the client can have a simple logic.

推荐答案

基于@Gus对这个问题的回答(

Based on the answer from @Gus to this question (AsyncResult and handling rollback) it seems that bindError is what I needed. I created a similar to his bindError bindExn, and it seems to work as well, so now both error and exns can be converted to Ok:

(来自Gus):

/// Apply a monadic function to an AsyncResult error  
let bindError (f: 'a -> AsyncResult<'b,'c>) (xAsyncResult : AsyncResult<_, _>) :AsyncResult<_,_> = async {
    let! xResult = xAsyncResult 
    match xResult with
    | Ok x -> return Ok x
    | Error err -> return! f err
}

(我的代码):

let bindExn
    (f: exn -> AsyncResult<'a,'b>)
    (xAsyncResult:AsyncResult<_,_>)
    : AsyncResult<'a,'b>
    =
    async {
        let! res =
            xAsyncResult
            |> Async.Catch
            |> Async.map(function
                | Choice1Of2 res -> res |> AsyncResult.ofResult
                | Choice2Of2 (ex:exn) ->
                    f ex
            )
        return! res
    }

这篇关于如何在F#的面向铁路的程序中从错误跟踪切换回成功跟踪?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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