簡體   English   中英

在 f# 中使用 Result 提取結果或聚合錯誤的干凈方法

[英]Clean way to extract results, or aggregate errors using Result, in f#

我有一個從網格收集數據的系統。 它按行組織。 處理的每一行都返回一個Result<data, string list> object。 錯誤案例中的列表是解析過程中遇到的錯誤列表。 每行可以有多個錯誤,但只有一個有效結果。

如果沒有錯誤,我想將數據聚合到列表data list中,或者如果至少有一個錯誤,我想在string list表單中制作完整的錯誤列表。

最終返回類型為Result<data list, string list>

我有以下代碼:

let hasErrors =
    gridRows |> List.exists (fun r -> match r with | Ok _ -> false | Error _ -> true)

// build the layer list, or return the errors
match hasErrors with
| false -> Ok (
            gridRows
            |> List.map (fun r ->
                match r with
                | Ok layer -> layer
                | Error _  -> failwith "this should never execute"
            )
          )
| true -> Error (
                gridRows
                |> List.collect (fun r ->
                    match r with
                    | Ok _ -> []
                    | Error messages -> messages
                )
             )

但這感覺非常笨重且難以閱讀。

使用 Result<>,有沒有辦法:

  • 如果有任何錯誤,收集列表中的所有錯誤元素並使用該列表返回結果
  • 如果沒有錯誤,則收集列表中的所有 ok 元素並使用該列表返回結果

您在這里要做的是折疊,這是一種迭代列表的所有元素的方法,同時保持某種 state 就像您 go 一樣。 在這種情況下, Ok將是最終的結果值 - 所有值均正常或所有Error均出錯。

折疊 function 將非常簡單:

let f state item = 
    match state, item with
    | Ok prevResults, Ok res -> Ok (prevResults @ [res])
    | Ok _, Error errs -> Error errs
    | Error errs, Ok _ -> Error errs
    | Error prevErrs, Error errs -> Error (prevErrs @ errs)

這個 function 同時查看“迄今為止累積的結果”(也稱為“狀態”)和當前項目,並針對四種可能性中的每一種,返回適當的新“迄今為止累積的結果”。

然后你可以使用這個 function 折疊列表,初始 state 是Ok []

gridRows |> List.fold f (Ok [])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM