6.4.2 使用 bind 函数

728 篇文章 1 订阅
349 篇文章 0 订阅

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) -> 'aoption -> 'b option) = (...)

 

bind 和 map 的类型签名的区别,只在于函数参数的类型,正如我们刚才讨论。只通过类型理解函数的行为,是函数程序员非常重要的技能。在这里,如果我们假定函数的行为合理,类型能够提供函数功能的很好线索,我们可以分析所有情况,推断出函数的行为规范:

■输入值为 None,bind 不能运行提供的函数,因为它不能安全地获取类型 'a 的值,因此,立即返回 None。

■输入值为 Some,类型 'a 所包含的值 x,bind 可以调用提供的函数,用 x 作为参数值。它仍然可能返回 None,但是,更合理的行为,是在可能时调用该函数。根据作为参数值的给定函数返回,有两种不同的情况:

— 如果函数返回 None,bind 操作没有类型 'b 的值,所以,整体结果必须返回 None。

— 如果函数返回 Some(y),那么,bind 操作有类型 'b 的值 y,只在这种情况下,才返回Some 结果,因此,整体结果是 Some(y)。

现在,我们可以使用绑定,重写外层的模式匹配,因为,它提供了一种即使在成功读取第一个输入时,仍然返回未定义值(None)的方法。清单 6.11 是 readAndAdd 的最终版本。

 

清单 6.11 使用 bind 和 map 计算两个可选值的和(F#)

let readAndAdd2() =

  readInput()|> Option.bind (fun num –>    [1]

    readInput()|> Option.map ((+) num) )   [2]

 

读取第一个输入后,我们把它传递给绑定操作[1],执行给定的 lambda 函数,只在输入包含值时;在 lambda 函数内部,我们读取第二个输入,并把它映射到结果值[2];用于映射的操作把第一个输入与这个值相加。在清单中,我们把操作写成加号,和散应用,而不是显式指定 lambda 函数;如果对比清单 6.10 的代码,可以发现,这种写法肯定更简洁。现在,我们要详细分析它的工作原理了。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值