
F#
文章平均质量分 59
心想才事成
这个作者很懒,什么都没留下…
展开
-
12.2.2 无穷序列
12.2.2 无穷序列 在前一章中,我们简单演示了如何使用延迟值实现延迟列表。这种数据结构可以用来创建无穷数据结构,比如,从零开始的整数列表。这是可能的,因为每个元素的计算被推迟了:只当我们访问元素时,才计算它的值,并且,每次只关注一个元素的计算。 使用 seq 表示序列是相似的。该接口有一个方法 MoveNext,关注下一个计算的元素。序列可能是无窜的,就是说翻译 2011-11-13 16:23:56 · 761 阅读 · 0 评论 -
12.3.1 用迭代器转换序列
12.3.1 用迭代器转换序列 到目前为止,我们只能用迭代器,来从单一的数据块(如果任何)生成序列。然而,迭代器的一个常见用途,是以某种方式把一个序列变换成另一个。作为一个简单的例子,这里有一个方法,取一个数字的序列,返回平方序列:IEnumerable Squares(IEnumerable numbers) { foreach(int i in nu翻译 2011-11-13 21:10:27 · 619 阅读 · 0 评论 -
12.3 处理序列
12.3 处理序列 处理序列,有多种选项,包括从低级的技术,能控制所有的详细信息,但难表达更复杂而通常的处理模式,到更高级的技术,虽然不能表达我们可能想要的所有,但表达非常优雅。 在 C# 中,最低级别 (除了直接实现 IEnumerable 接口) 是使用迭代器块,读取输入的序列,既可以使用 foreach,也可以使用枚举对象。更高级,我们可以使用预定义(或者翻译 2011-11-13 17:10:33 · 466 阅读 · 0 评论 -
12.3.3 平面映射(flattening projection)
12.3.3 平面映射(flattening projection) 平面映射,可以为来自源集合的每个元素的元素生成一个序列,合并所有返回的序列。我们很快就会看到,这是一个基本操作,可以用来定义其他处理操作,包括映射和筛选。有关平面映射唯一的事情就是,为每个输入元素生成多个输出元素。注意 在 LINQ 库中,这个操作被称为 SelectM翻译 2011-11-15 21:32:58 · 938 阅读 · 0 评论 -
12.4 可选工作流(alternative workflows)
12.4 可选工作流(alternative workflows) 计算表达式(Computation expressions)是一种 F# 功能,部分灵感是来自 Haskell 的单子(monads)。单子有个不好的名声,对于脑 bustingly 有困难的人来说,但是,也不用担心。我们将看一下如何实现一套有趣的技术,可以在 C# 中很好地处理 Option 值。还将看到如何翻译 2011-11-16 09:43:56 · 693 阅读 · 0 评论 -
12.4.1 自定义查询表达式
12.4.1 自定义查询表达式 原则上,我们可以使用查询处理任何支持绑定操作的类型。这是用于函数式编程中的标准名称,像上一节中所示的类型签名的函数。从技术角度讲,我们需要实现可以由 C# 编译器所使用的方法,把查询表达式转换为标准的函数调用。我们将为 12.6 节中的 Option 的类型实现这些方法。该类型没有实现 IEnumerable,所以,标准查询运算符不能使用。翻译 2011-11-16 11:20:38 · 861 阅读 · 0 评论 -
12.4.2 自定义 F# 语言
12.4.2 自定义 F# 语言 至止,我们所讨论过的序列表达式,都是用 seq 标识符表示,后面的代码块括在大括号中。然而,F# 允许创建我们自己的标识符,给代码块以特殊意义。通常,这个功能称为计算表达式(computation expressions),序列表达式是它的一个特例,它是由 F# 核心实现,并由编译器优化的。 我们已经看到过,计算表达式可以包含标准翻译 2011-11-16 17:15:02 · 686 阅读 · 0 评论 -
6.8.2 列表的绑定操作
6.8.2 列表的绑定操作 我们只讨论了选项值的绑定操作,但正如我们将在第 12 章看到的,它通常是非常重要的函数式操作。清单 6.26 显示了选项值绑定操作的类型签名,以及如果我们定义列表的绑定操作,它看起来又会怎样。 Listing 6.26 Signatures of bind operations (F#) Option.bind : ('a -> 'b o翻译 2011-05-24 14:32:00 · 521 阅读 · 0 评论 -
12.5.2 写计算
12.5.2 写计算 C# 查询表达式和 F# 计算表达式,可以使用函数,以非标准方式的行为(通过返回一些一元值) ,就好像返回普通的值。我们在这一节中使用的计算类型是 ValueWrapper ,因此,原始函数将返回ValueWrapper 类型的值,而不只是 T。 实现这些函数,既可以使用另外的查询或计算表达式,也可以通过直接创建计算类型的值。有些计算表达式可以封装复翻译 2011-11-17 11:39:58 · 557 阅读 · 0 评论 -
12.5 自定义计算的第一步
12.5 自定义计算的第一步 本节中的示例并没有任何实际的用处,但是,它演示了一些核心概念。设计自定义计算中的第一个任务就是,考虑由这个计算生成的值所表示的类型。翻译 2011-11-17 08:53:36 · 541 阅读 · 0 评论 -
12.5.1 声明计算类型
12.5.1 声明计算类型 在这个示例中的计算类型(在 Haskell 术语中的一元类型)称为 ValueWrapper,它只是存储泛型类型参数 t 的值,并不会为这个类型增加任何其他功能。这意味着,这个计算只处理标准值,但是,我们能够写代码(来增加功能),用 C# 中的查询表达式, F# 中的计算表达式。 清单 12.17 显示了在 C# 和 F# 中的类型声明翻译 2011-11-17 09:25:12 · 514 阅读 · 0 评论 -
6.8.1 映射、筛选和折叠
6.8.1 映射、 筛选和折叠 映射、筛选和折叠是函数编程中最常见的操作。在处理函数式列表时,我们已经用到过,但它们也支持所有其他集合类型(我们将在第 10 和 12 章讨论其中一些) 。这些操作并不限于集合,所有的操作都可用于处理选项类型。 清单 6.25 显示了映射、筛选和折叠函数的几个签名类型。该列表包括了 Option.filter 和 Option.fold 函翻译 2011-05-24 10:15:00 · 534 阅读 · 0 评论 -
12.5.3 在 F# 中实现计算生成器
12.5.3 在 F# 中实现计算生成器 在计算表达式块前面的的标识符,是一个类的实例,它把所需的操作实现成为一个实例成员。许多操作都是可用的:我们不必要支持所有的。用 Bind 和 Return 成员实现最基本的操作。当 F# 编译器看到计算表达式时,就像清单 12.18 中的,它会将计算表达式转换为 F# 代码,使用这些成员。转换的 F# 示例如下所示: value.B翻译 2011-11-17 16:49:32 · 770 阅读 · 0 评论 -
12.5.4 在 C# 中实现查询运算符
12.5.4 在 C# 中实现查询运算符 当我们在清单 12.14 中,讨论序列和分析 SelectMany 操作时,已经看到如何把 C# 查询转换为方法调用。我们将只支持查询以 select 子句结尾,而忽视那些仅对集合有用的情况,比如分组。这意味着,我们就需要实现 Select 扩展方法。 我们前面说过,第二个和随后的 from 子句被转换成对 Select翻译 2011-11-17 18:06:14 · 619 阅读 · 0 评论 -
12.7.1 创建日志记录的计算
12.7.1 创建日志记录的计算 这个计算将产生一个值,并能够将消息写入到本地日志记录的缓冲区。这意味着,计算的结果将是一个值,和包含这些消息的字符串列表。再次,我们还是使用有一个识别器的差别联合,表示这个类型:type Logging = | Log of 'T * list 这个类型非常类似于我们先前讨论的 ValueWrap翻译 2011-11-18 20:42:43 · 582 阅读 · 0 评论 -
12.7.3 使用计算表达式进行重构
12.7.3 使用计算表达式进行重构 在前一章中,我们看到一些重构函数式程序的方法。最后一个主题是延迟性,它变改代码的执行方式,而不影响程序的结果。从某种意义上讲,添加延迟性也可看作是一种重构技术。计算表达式类似之处在于,它们增加其他方面的代码,而不改变其核心意义。提示 在计算表达式和延迟性之间有密切的关系,创建一个计算表达式,把代码转换翻译 2011-11-19 15:34:00 · 593 阅读 · 0 评论 -
12.7.2 创建日志记录计算
12.7.2 创建日志记录计算 清单 12.24 首先开始通过实现两个辅助函数,用于读取和写入控制台。两者还会把一条消息写入日志,所以,它们将括在 log 计算块中。为了显示如何组合非标准计算,我们在第三个函数中,使用了这两个函数。在我们前面的示例中,使用 let! 基元,但是,清单 12.24 还引入了 do!。Listing 12.24 Logging u翻译 2011-11-19 14:29:23 · 520 阅读 · 0 评论 -
13 第十三章 异步和数据驱的编程
13 第十三章 异步和数据驱的编程本章介绍 ■ 异步工作流编程 ■ 使用 F# Interactive 浏览数据 ■ 使用度量单位定义类型 ■ 处理与可视化数据 我们首先引述了一次对比尔 · 盖茨的采访,他谈到,他有兴趣的编程任务的类型,并描述了编写应用程序的典型情况: 从 web 获取数据,不只是把它当作文本,而翻译 2011-11-20 14:15:27 · 573 阅读 · 0 评论 -
6.8 通用处理语言
6.8 通用处理语言 如经过这一章的课程,我们已经看到几个递归模式,比如一个叫映射的操作,既可用于选项的值,也可用于列表。我们还用它处理元组,并实现了 mapFirst 和 mapSecond 的函数。 许多不同的值共享一组相似的处理函数,因此,把这些操作认为当作一种通用语言是意义的。但是,操作的名称可以随值而不同:类型签名中的相似之处往往要比名称中的相似之处有更好的线索翻译 2011-05-23 16:40:00 · 403 阅读 · 0 评论 -
6.7.2 理解列表函数的类型签名
6.7.2 理解列表函数的类型签名 我前面提到过,我们已用函数来筛选和映射列表,但使用都很直观。在本节中,我们将看看它们的类型签名,会看到,我们可以推断一个高阶函数只使用此信息做什么。 当然,在一般情况下,你不能通过看函数的类型,就知道它能做什么,但对于泛型和高阶函数,例如那些用来处理列表的函数,通常是可能的。如我们前面所见的,处理泛型值的函数则不能单独处理值太多,因为,翻译 2011-05-20 15:30:00 · 519 阅读 · 0 评论 -
6.7.1 F# 中实现列表
6.7.1 F# 中实现列表 虽然我们已经处理过 F# 中的列表,还在 C# 中实现了相同功能,但还没有探索在 F# 中如何实现列表类型。当我们前面讨论列表时,看到列表既可以表示为零(nil)值(空列表),也可以表示成 cons cell,包含一个元素和对列表中的其余部分的引用。 现在,如果我们看看上一章中的值的图库,这与带有两个选项的可选值完全一样。有一点稍微不同, 列翻译 2011-05-19 11:38:00 · 450 阅读 · 0 评论 -
13.1.1 异步工作流为什么重要?
13.1.1 异步工作流为什么重要? 假设我们要下载 web 页的内容,以便可以在我们的应用程序中使用。我们可以使用来自 System.Net 命名空间下的 WebClient 类,但是,不会演示当我们需要的问题,当我们运行复杂、长时间运行的操作时。相反,我们将首先显式创建 HTTP 请求,然后,下载数据:var req = HttpWebRequest.Create翻译 2011-11-20 16:53:27 · 1075 阅读 · 0 评论 -
12.6 实现选项的计算表达式
12.6 实现选项的计算表达式 在 12.4 节中,我们用选项值作为示例,介绍了用 LINQ 查询和 F# 的计算表达式创建非标准计算的概念。我们所写的代码处理选项值,有自定义的值绑定来读取实际值,就好像是一个标准值。我们已经看到如何转换计算表达式,知道我们的 Bind 成员会接收一个值,和一个 lambda 函数。我们只想执行这个 lambda 表达式,有我们的选项类型计翻译 2011-11-18 16:25:41 · 688 阅读 · 0 评论 -
12.7 给计算增加日志记录
12.7 给计算增加日志记录 日志通常可以使用全局可变状态实现。然而,如果我们想要避免使用全局可变状态,并保持程序的纯函数性,又会如何呢?我们会有一个选择,就是把日志记录器的状态作为额外的参数值,传递我们要调用的每个函数。实现可能非常困难(想象一下,如果我们决定将另一个参数添加到这个状态中!)。 要解决这个问题,我们可以创建一个自定义计算类型,启用日志记录,隐藏翻译 2011-11-18 18:25:30 · 658 阅读 · 0 评论 -
6.7.3 实现列表函数
6.7.3 实现列表函数 不显示如何实现刚才我们看到的筛选和映射函数,先来看看从第 3 章开始创建的函数。因为,所有列表处理函数都有类似的结构,你在看下面的示例后,可以能够实现其他任何的函数。 在第 3 章,我们写了一个函数,它可以列表中的所有元素求和或求积。后来,我们就意识到它是比首次出现时更有用:我们看到,它也能用来查找最小或最大元素。那时,我们没有讨论过泛型,因此,翻译 2011-05-23 16:23:00 · 468 阅读 · 0 评论 -
12.8 第十二章小结
12.8 第十二章小结 在本章的第一部分,我们讨论了 .NET 序列,由 IEnumerable 类型表示,在 F# 中也称为 seq 。我们开始讨论生成序列的技术,包括高阶函数、迭代器和 F# 序列表达式。我们看到,序列是延迟的,能够创建无穷序列。我们看到了一个实际的示例,使用颜色的无穷的序列,将绘制图表的代码,从在图表中使用的生成颜色的代码中分离出来。 接下翻译 2011-11-19 16:17:41 · 473 阅读 · 0 评论 -
第四部分 函数式编程
第四部分 函数式编程 虽然函数式编程肯定是优雅的,但是,你可能更感兴趣的是其实用目的:作为一种通用的风格,是有用的,在某些问题域中,它肯定是出色的。我们已经看到的例子,比如,第 4 章中绘制饼图的应用程序,和第 11 章中简单的照片浏览器,这些示例的主要目的是,为了演示特定的概念和技术。 第四部分则不同。在每一章中,我们将花大量时间,讨论实际问题,使用最适当的翻译 2011-11-19 19:25:15 · 431 阅读 · 0 评论 -
13.1 异步工作流
13.1 异步工作流 有许多地方需要使用异步操作。当我们使用磁盘、调用 web 服务,或者连接到数据库时,异步工作流可能有显著的性能优势。当应用程序执行异步操作时,很难预测什么时修操作将完成。如果不能正确处理异步操作,应用程序就会效率低下,甚至可能停止响应。 写出能够执行异步操作,而不会阻止调用线程的代码,避免出现问题是必要的,但是,使用当前的技术很难实现。在 F# 中翻译 2011-11-20 14:42:57 · 531 阅读 · 0 评论 -
13.1.2 异步下载网页
13.1.2 异步下载网页 在我们使用异步工作流来获取网页内容之前,需要引用 FSharp.PowerPack.dll 库,它包含许多 .NET 方法的异步版本。当开发独立的应用程序时,可以使用添加引用命令。在这一章中,我们将使用互动开发模式,创建一个新的 F# 脚本文件,使用 #r 指令(清单 13.1)。 Listing 13.1 Writing code using翻译 2011-11-21 11:26:47 · 767 阅读 · 0 评论 -
13.2 连接到世界银行
13.2 连接到世界银行 我们在一章讨论有关探索式编程(explorative programming),放在异步工作流上,这决不是偶然的。我们今天要处理的很多有趣的数据源,都是以 web 服务的形式,或者是其他基于 web 的应用程序,在线可用。如我们所见,异步工作流是 F# 获取数据的本质特征。 高效地下载数据并不是我们唯一的问题。数据源返回的数据通常是非类型化的格式翻译 2011-11-22 11:15:27 · 587 阅读 · 0 评论 -
13.2.2 从故障中恢复
13.2.2 从故障中恢复 世界银行服务对每个用户密钥每一天请求数量有限制,也限制了请求的频率。这意味着,如果我们一次运行大量的请求,有些可能会返回错误。解决方法是捕获异常,稍后重试请求。 清单 13.7 实现一个循环,重复执行的请求,直到成功,或者尝试 20 次。使用异常报告失败, 使用 F# 的 try … with 结构捕捉异常。Listi翻译 2011-11-22 19:13:00 · 746 阅读 · 0 评论 -
13.2.1 访问世界银行的数据
13.2.1 访问世界银行的数据 我们在本章中使用的数据源,是由世界银行提供的服务,它是为发展中国家提供资金和知识的国际组织。作为其工作的一部分,该组织需要确定对评估发展中国家,哪种类型的支持最有效,确定需求在哪里,以及对经济、生活质量、环境是否产生了影响。世界银行有一组数据,称为世界发展指标(World Development Indicators),它包含了许多国家的信息,而且翻译 2011-11-22 15:07:42 · 1040 阅读 · 0 评论 -
13.1.4 创建基元工作流
13.1.4 创建基元工作流 F# PowerPack 库包含许多重要的 I/O 操作异步版本,但是,它可不能包括所有。为此,F# 库还提供了构建自己的基元工作流的方法。如果要运行在工作流内部的操作,使用的标准 .NET 模式,并提供了 BeginOperation 和 EndOperation 方法,可以使用 Async.FromBeginEnd 方法。如果你把这两种方法给翻译 2011-11-21 19:41:35 · 719 阅读 · 0 评论 -
3.3.3 C# 中的函数式列表
3.3.3 C# 中的函数式列表 若要显示函数式列表类型是如何工作的,让我们看看如何在 C# 中可以实现相同的功能。有几种方法来表示这一事实,列表既可以是空的,也可以是有头和尾。面向对象的解决方案将写入抽象类 FuncList,有两个派生类来表示这两种情况——例如,EmptyList 和 ConsCellList。为使代码尽可能简单,我们只使用一个单类,有个属性 IsEmpty,它翻译 2011-04-02 12:15:00 · 712 阅读 · 0 评论 -
13.3 探索并获取数据
13.3 探索并获取数据 就像我们在最后的几个例子中所看到的,世界银行数据服务返回数据是 XML 文档,这样,我们可以写任何代码,以有意义的方式处理数据之前,需要将它转换为 F# 类型。在第 7 章,我们在XML 和我们自己自定义的差别联合类型之间进行过转换,但在这里,我们要使用的是元组和序列。这是因为,这样的数据结构很简单,当我们交互式处理数据时,需要频繁地修改代码,既要调整翻译 2011-11-23 09:10:00 · 645 阅读 · 0 评论 -
13.3.1 实现 XML 辅助函数
13.3.1 实现 XML 辅助函数 LINQ to XML 主要用于 C# 和 VB,在 F# 中使用可能有些麻烦。例如,F# 不支持隐式类型转换(因为这会使类型推断复杂),所以,每次我们指定元素名,必须使用 XName.Get,而不是只使用一个字符串。或者,我们可以写一个简单的工具函数或自定义运算符,来完成这些。 我们可以很容易地实现几个 F# 函数,把 LINQ t翻译 2011-11-23 15:03:17 · 650 阅读 · 0 评论 -
11.4.2 在照片浏览器中缓存值
11.4.2 在照片浏览器中缓存值 在下一个示例中,我们要写一个应用程序,找出指定文件夹中的所有照片,并显示为一个列表。当用户选择一张照片,应用程序调整它的大小,并显示在一个窗口中。(为了简便起见,我们不会允许用户调整窗口大小)。当我们画了这张照片时,需要调整其大小以适合屏幕,然后,显示调整大小后的图像。 很明显,我们不想在应用程序启动时调整所有照片的大小:对于翻译 2011-11-03 16:15:45 · 840 阅读 · 0 评论 -
11.4.1 无穷列表
11.4.1 无穷列表 这一节的标题可能听起来有点奇怪(或疯了),所以,我们会提供一个字面解释。我们用得很多的数据结构之一是函数式列表。我们也可能想要表示逻辑上无穷列表,例如,所有质数的列表。事实上,我们不会使用所有的数字,但可能会处理这样的数据结构,而不考虑长度。如果列表是无穷的,我们就能够访问我们需要尽可能多的数字。 除了数学上的挑战,同样的概念在许多主流编翻译 2011-11-02 21:35:55 · 648 阅读 · 0 评论 -
11.5 第十一章小结
11.5 第十一章小结 这一章的主题主要是函数编程的重构,我们已经看到了很多的示例和概念。我们首先讨论了在数学意义上的重构,可以看到,在数学意义上,可以很容易推导出"代码",因此,可以看到一个特定的改变在何时改正。由于其根源在数学中,函数式编程通常有相同的属性。 我们首先探讨如何能够使用函数类型,以减少代码重复,这是重构的简单情况。然后,我们看到,函数式编程如何翻译 2011-11-03 16:51:52 · 373 阅读 · 0 评论 -
13.3.2 提取区域的代码
13.3.2 提取区域的代码 我们下载函数的结果是一个字符串,所以,需要将字符串作解析为 XML 文档。我们将频繁需要这个操作,所以,要写一个简单的打包函数,使用 worldBankDownload 下载数据,返回结果为 XDocument 对象。下载执行异步,因此,要使用异步工作流实现这个函数:let worldBankRequest(props) = as翻译 2011-11-23 22:29:27 · 682 阅读 · 0 评论