我可以在 F# 中对选项检查进行分组吗

can I group option checks in F#

我有以下代码:

let i  = instrumentFromString arguments.[1]
let o  = podManager.GetExchange().GetLeverageOptions(i.Value)
let l  = parseInt arguments.[2]     |> Option.bind (fun x -> if i.IsSome && o |> List.contains(x) then Some x else None)
let wl = parseDecimal arguments.[3] |> Option.bind (fun x -> if x > 0m && x <= 1m then Some x else None)
let ws = parseDecimal arguments.[4] |> Option.bind (fun x -> if x > 0m && x <= 1m then Some x else None)

解析输入系统的指令

然后是:

match i.IsSome && l.IsSome && wl.IsSome && ws.IsSome with
| true ->
    ... do stuff
    
| false ->
    stringBuffer {
        if i.IsNone then             $"unkown instrument 'arguments.[1]'\n"
        if l.IsNone && i.IsSome then $"invalid leverage, instrument '{i.Value.Ticker}' supports {podManager.GetExchange().GetLeverageOptions(i.Value)}\n"
        if wl.IsNone then            $"invalid long share, must be > 0 and <= 1\n"
        if ws.IsNone then            $"invalid short share, must be > 0 and <= 1\n"
    }

我觉得这有点令人费解,因为我解析了参数,然后验证它们,然后确保它们都正常,如果不正常,我将逐一检查一遍。

所以一个选项是像这样转换解析行:

let l  = parseInt arguments.[2] |> Option.bind (fun x -> if i.IsSome && o |> List.contains(x) then Result.Ok x else Result.Error "my error message")

所以它会把测试和报错信息分组,但我还是要检查有没有报错,然后再一一解析可能的报错。

我想我可以累加 ok / error 值的计算表达式可以工作,但也存在 Option / Result 转换的问题。

是否有一些很好的惯用方法来处理我错过的这种情况?

我建议您将选项转换为结果并使用 FsToolkit.ErrorHandling 中的 validation 生成器。这使用 F# 5 语言功能。您可以在 F# 脚本中试用此代码:

#r "nuget: FsToolkit.ErrorHandling,2.0.0"
open FsToolkit.ErrorHandling

let a : Result<string, string> = Ok "a"
let b : Result<string, string> = Error "b missing"
let c : Result<string, string> = Ok "c"
let d : Result<string, string> = Error "d missing"

validation {
    let! a = a
    and! b = b
    and! c = c
    and! d = d
    return a, b, c, d
}
// Returns: Error ["b missing"; "d missing"]

您应该能够将此示例应用到您的代码中。