如何“连接”两个选项

Jus*_*inM 4 f#

我正在浏览 F# 文档,想知道 Option 模块中的“缺失”函数。有一个map2需要两个选项并且似乎logical AND对它做了一个。如果其中一个为 None,则结果为 None。否则,如果您有 Some(a) 和 Some(b),它将返回 Some(f(a,b))。

功能在哪里logical OR?我期望有一个类似的函数,如果只有一个是 Some,则返回它。但如果两者都是 Some,它会像逻辑 AND 情况一样执行 Some(f(a,b)) 。我可以手动写出来,模式匹配没有问题。

let concat f a b =
    match a, b with
    | Some(a), Some(b) -> Some(f a b)
    | Some(a), None -> Some(a)
    | None, Some(b) -> Some(b)
    | _ -> None
Run Code Online (Sandbox Code Playgroud)

实际上,如果您有一个可选数字列表并且想要将它们相加,这可能很有用。如果列表为空或仅包含“无”值,则答案为“无”。None 不会影响结果,就像零一样。或者是几个可选的字符串,并且您想要将它们连接起来。

我假设由于 F# 在标准库中似乎没有这个函数,所以我一定是以错误的方式思考问题的。或者有更简洁的方法吗?

Tom*_*cek 5

您正在寻找的将是以下类型的函数(请注意,该类型与 的类型不同,map2因为作为参数提供的两个选项需要具有相同的类型(以便当另一个选项时您可以返回其中一个或另一个)不可用):

('a -> 'a -> 'a) -> 'a option -> 'a option -> 'a option
Run Code Online (Sandbox Code Playgroud)

据我所知,标准 F# 库中不存在此函数,但它听起来像是一个潜在有用的函数。例如,这在 Haskell 中存在unionWith(请参阅减速器包中的 unionWith)——当然,以更通用的形式。

我认为将其实现添加到“utils”库或建议添加到 F# 核心库是一个非常合理的想法。我也会match像你一样使用它来实现这个。尽管有趣的是,您也可以使用map2and来获得此行为orElse(我认为,可读性较差并且可能更慢):

let unionWith f a b = 
  Option.map2 f a b |> Option.orElse a |> Option.orElse b
Run Code Online (Sandbox Code Playgroud)