【问题标题】:F# Option chainingF# 选项链接
【发布时间】:2020-07-07 01:28:27
【问题描述】:

F# Option 类型是从函数返回“结果或失败”的好方法。

有时您需要按照以下方式链接这些函数:

  1. 调用第一个函数
  2. 如果它返回 Somewhat,则将whatever传递给第二个函数并返回结果
  3. 否则,直接返回无

当然这可以通过模式匹配来完成;以这种方式实现模式匹配的函数的实际代码片段:

    match mtch env a0 a1 with
    |Some env->
        mtch env b0 b1
    |None->
        None

但感觉应该有一种更紧凑的方式来表达这个常见的习语,也许还有更高阶的函数。有这样的吗?

【问题讨论】:

标签: f#


【解决方案1】:

您可以使用计算表达式。我将使用此页面上的示例:https://fsharpforfunandprofit.com/posts/computation-expressions-intro/

创建计算:

type MaybeBuilder() =

    member _.Bind(x, f) = 
        match x with
        | None -> None
        | Some a -> f a

    member _.Return(x) = 
        Some x

let maybe = new MaybeBuilder()

返回选项的示例函数:

let divideBy bottom top =
    if bottom = 0
    then None
    else Some(top/bottom)

使用 Computation 和 chaining divideBy 的工作流程:

let divideByWorkflow init x y z = 
    maybe{
        let! a = init |> divideBy x
        let! b = a |> divideBy y
        let! c = b |> divideBy z
        return c
    }

用法示例:

let good = divideByWorkflow 12 3 2 1 //Some 2
let bad = divideByWorkflow 12 3 0 1 //None

【讨论】:

  • 为 Maybe 实现 Zero 案例通常是个好主意。
【解决方案2】:

FSharp.Core 中有一个Option 模块,提供“选项的基本操作”。具体来说,Option.bind 的签名与您的用例匹配:

binder:('T -> 'U 选项) -> option:'T 选项 -> 'U 选项

它在 VisualStudio 弹出提示中指出 bind f inp evaluates to match inp with None -> None | Some x -> f x.

// The actual argument values are not important here
let env, a0, a1, b0, b1 = (), (), (), (), () 
let mtch env _ _ = Some env // or might be None

match mtch env a0 a1 with
|Some env -> mtch env b0 b1
|None -> None

mtch env a0 a1
|> Option.bind (fun env -> mtch env b0 b1)

您甚至可以通过为选项操作定义自定义运算符来改进这一点。

let (>>=) ma f = Option.bind f ma
let (>>.) ma f = Option.map f ma

mtch env a0 a1
>>= fun env -> mtch env b0 b1
>>= ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    相关资源
    最近更新 更多