避免嵌套 `Result<'T,'TError>`
avoiding nesting `Result<'T,'TError>`
假设我们有这个 input
:
let input =
[
"0.10"
"0.21"
"forty"
"5.32"
"q6.20"
]
将此输入映射到 F# 结果导致 Result<'T,'TError> list
:
open System
let output =
input
|> List.map (
fun s ->
match Decimal.TryParse s with
| true, i -> Ok i
| _ -> Error $"failed to parse `{s}`"
)
output |> printf "%A"
[Ok 0.10M; Ok 0.21M; Error "failed to parse `forty`"; Ok 5.32M;
Error "failed to parse `q6.20`"]
这是一种普遍接受的收集结果的方式吗?
或者,是否存在可伸缩性和性能方面的问题,以至于整个列表只返回一个聚合结果?像 Result<'T,'TError list>
这样的东西? FsToolkit.ErrorHandling
[GitHub] 是否适用于此,或者我是否缺少融入语言的模式?
此解决方案是否会处理列表的列表以避免返回 Result<Result<'T,'TError> list>, 'TError>
?
您提到的所有选项在某些情况下都有用。
list<Result<decimal, string>>
表示个别值可能无效,但列表本身的转换不能失败的情况
Result<list<Result<decimal, string>>, string>
表示个别值可能无效的情况,还有一些其他原因导致列表处理本身可能失败
Result<decimal list, string list>
表示您要么正确处理了整个列表,要么处理失败并且在此过程中收集了多个错误。
我认为有趣的情况是最后一个 - 如果您想获得有效列表或解析错误列表,您可以编写以下内容:
let merged = output |> List.fold (fun res v ->
match v, res with
| Ok v, Ok res -> Ok(v::res)
| Ok _, Error errs -> Error(errs)
| Error e, Error errs -> Error(e::errs)
| Error e, Ok _ -> Error [e]) (Ok [])
假设我们有这个 input
:
let input =
[
"0.10"
"0.21"
"forty"
"5.32"
"q6.20"
]
将此输入映射到 F# 结果导致 Result<'T,'TError> list
:
open System
let output =
input
|> List.map (
fun s ->
match Decimal.TryParse s with
| true, i -> Ok i
| _ -> Error $"failed to parse `{s}`"
)
output |> printf "%A"
[Ok 0.10M; Ok 0.21M; Error "failed to parse `forty`"; Ok 5.32M;
Error "failed to parse `q6.20`"]
这是一种普遍接受的收集结果的方式吗?
或者,是否存在可伸缩性和性能方面的问题,以至于整个列表只返回一个聚合结果?像 Result<'T,'TError list>
这样的东西? FsToolkit.ErrorHandling
[GitHub] 是否适用于此,或者我是否缺少融入语言的模式?
此解决方案是否会处理列表的列表以避免返回 Result<Result<'T,'TError> list>, 'TError>
?
您提到的所有选项在某些情况下都有用。
list<Result<decimal, string>>
表示个别值可能无效,但列表本身的转换不能失败的情况Result<list<Result<decimal, string>>, string>
表示个别值可能无效的情况,还有一些其他原因导致列表处理本身可能失败Result<decimal list, string list>
表示您要么正确处理了整个列表,要么处理失败并且在此过程中收集了多个错误。
我认为有趣的情况是最后一个 - 如果您想获得有效列表或解析错误列表,您可以编写以下内容:
let merged = output |> List.fold (fun res v ->
match v, res with
| Ok v, Ok res -> Ok(v::res)
| Ok _, Error errs -> Error(errs)
| Error e, Error errs -> Error(e::errs)
| Error e, Ok _ -> Error [e]) (Ok [])