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 的代码,可以发现,这种写法肯定更简洁。现在,我们要详细分析它的工作原理了。

时间: 2024-10-28 21:14:21

6.4.2 使用 bind 函数的相关文章

(十一)socket、connect、bind函数详解

一.socket函数 1.头文件: #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> 2.函数原型: int socket(int domain, int type, int protocol); socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符. dimain:域,网络域,网络地址范围(IPV4或IPV6

socket bind函数

1 #include<stdio.h> 2 #include<sys/types.h> 3 #include<sys/socket.h> 4 #include<netinet/in.h> 5 #include<arpa/inet.h> 6 #include<unistd.h> 7 #define PORT 2345 8 #include<stdlib.h> 9 #include<string.h> 10 int

C++ bind函数适配器

在我之前的博客让类成员函数指针成为可调用对象里有提到bind函数适配器,现在在这里介绍一下. 适配器可以让某一个看上去像另一个行为,比如栈.队列等,底层使用链表去完成功能,我们通过操作底层链表去实现栈.队列等的行为.bind是函数适配器,通过bind返回的可调用对象去完成指定函数的功能. bind的头文件是<functional>,可使用命名空间std::placeholders的_n形式引用外部参数,属于C++11标准. 使用例子: // main.cpp #include <func

模拟实现兼容低版本IE浏览器的原生bind()函数功能

模拟实现兼容低版本IE浏览器的原生bind()函数功能: 代码如下: if(!Function.prototype.bind){   Function.prototype.bind=function(oThis){     if (typeof this !== 'function'){       throw new TypeError('调用者不是当前函数对象');     }       var aArgs = Array.prototype.slice.call(arguments, 1

C++拾遗--bind函数绑定

C++拾遗--bind函数绑定 前言 函数绑定bind函数用于把固定的参数与已知的函数进行绑定,形成新的函数,从而减少参数的个数,降低函数的调用难度.需要指出:bind就是函数适配器. bind函数 实例 #include <iostream> #include <functional> using namespace std; using namespace std::placeholders; int main() { auto fun = [](int *array, int

《Javascript高级程序设计》读书笔记之bind函数详解

为什么需要bind var name = "The Window"; var object = { name: "My Object", getNameFunc: function () { return function () { return this.name; } } }; alert(object.getNameFunc()()); //"The Window" object.getNameFunc()返回一个匿名函数,在全局环境调用该

angular.bind() 函数

angular.bind bind 函数有三个参数, 参一:是一个对象 参二:是一个 function 参三:是用来给参二传参数的,可写可不写,看你心情 参数也可以在调用函数的时候传,也可以当做第三个参数传 在函数的体内可以访问参数一的所有属性值 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document<

2.cocos2dx 3.2中语法的不同之处,lambada表达式的使用和function和bind函数的使用

1        打开建好的T32  Cocos2dx-3.2的一个项目 2        设置Cocos显示窗口的位置是在AppDelegate.cpp中: 3  设置自适应窗口大小的代码是在上面的代码后面紧接着就添加: glview->setDesignResolutionSize(480,320, ResolutionPolicy::EXACT_FIT); 3        cocos2d-x-3.2项目案例(3.2版本之后都去掉了CC前缀) 4        项目目录结构如下: 编写公共

理解bind函数

前言:之前一直不懂这个函数是干嘛的,最近慢慢有点懂了,说一说自己的理解~ 本文按以下3个方面来谈谈bind函数 1)对bind函数的理解: 2)如何使用bind函数 3)自定义bind函数 (https://msdn.microsoft.com/zh-cn/library/ff841995中有bind函数较详细的说明) (1)bind函数的理解 语法: function.bind(thisArg[,arg1[,arg2[,argN]]]) 首先不看传的参数,bind函数实现的功能就是将funct

Function.prototype.bind函数兼容处理

今天敲代码的时候,想了想bind函数 Function.prototype.bind = Function.prototype.bind || function (target) { var self = this; return function (args) { if (!(args instanceof Array)) { args = [args]; } self.apply(target, args); }; }; /*example 1*/ function f1(y, z){ re