bind函数,6.4.2 使用 bind 函数

6.4.2 使用 bind 函数
下一步,我们想消除外层的模式匹配。这样做,使用 Option.map 是不可能的,因为,该函数总是输入值 None 转换到 输出值 None,输入值 Some 转换到输出到携带另一个值的 Some。在外层的模式匹配中,我们要做的事情很不一样。即使输入值是 Some,仍可能返回 None,如果读第二个输入失败。这意味着,我们指定为参数值的 lambda 函数的类型不应该是 'a -> 'b,而是 'a ->'b option。
像这样的操作在函数编程的术语中,称为绑定(bind),它由标准的 F# 库提供。让我们探讨它的签名,看看此函数做了什么:
> Option.bind;;
val it : (('a -> 'b option) -> 'a option -> 'b option) = (...)
绑定和映射的类型签名中的区别只是在于函数的类型参数,正如我们刚才讨论。了解只使用这个类型的函数的行为,是函数程序员非常重要的技能。在这种情况下,类型为我们提供了函数可以做什么的很好线索,如果我们假定,它的行为合理。我们可以分析所有的情况,以推断出函数的行为规范:
■ 输入值为 None,绑定不能运行提供的函数,因为,它不能安全地获取类型 'a 的值,从而立即返回 None。
■ 输入值为 Some,携带类型 'a 的值 x,绑定可以调用提供的函数,用 x 作为参数值。它还可以返回 None,但是,一个更合理的行为,是在可能时,调用该函数。有两种不同的情况,取决于作为参数值的给定函数返回什么:
— 如果该函数返回 None,绑定操作没有类型 'b 的值,所以,它必须返回 None 作为整体的结果。
— 如果该函数返回 Some(y),那么,绑定类型 'b 的值 y,只在这种情况下,返回 Some 结果,因此,结果是 Some(y)。
使用绑定,我们现在可以写外层的模式匹配,因为,它给我们的一种方法,以返回未定义的值 (None),即使在成功读取第一个输入时。清单 6.11 显示了 readAndAdd 的最终版本。
Listing 6.11 Adding two options using bind and map (F#)
let readAndAdd2() =
readInput() |> Option.bind (fun num –>
readInput() |> Option.map ((+) num) )
读取第一个输入后,我们把它传递给绑定操作,执行给定的 lambda 函数,只在输入包含一个值时。在此 lambda 函数内部,我们读第二个输入,并把它映射到一个结果值。该操作用于映射第一个输入与这个值的相加。在此清单中,我们使用加法运算符来写这个操作,和偏应用,而不是显式指定 lambda 函数。如果你对比清单 6.10 的代码,可以看到,这个肯定更简洁。现在,让我们更详细地分析它的工作原理。
Tags:  if函数使用 if函数的使用 如何使用if函数 bind函数

延伸阅读

最新评论

发表评论