如何在F#中面向铁路的程序中从错误轨道切换回成功轨道?

  • 本文关键字:轨道 错误 成功 铁路 程序 f#
  • 更新时间 :
  • 英文 :


使用Scott Wlashin的AsyncResult,想知道如何从错误轨道切换到成功轨道。

伪代码:

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 回答,就好像它们是原始请求一样,以便客户端可以有一个简单的逻辑。

根据@Gus对这个问题的回答(AsyncResult 和处理回滚(,似乎 bindError 是我需要的。我创建了一个类似于他的 bindError bindExn,它似乎也可以工作,所以现在错误和 exns 都可以转换为 Ok:

(来自格斯(:

/// 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
}

最新更新