本章介绍
■ 表示和处理文档
■ 设计不可变数据结构
■ 数据表示形式之间的转换
■ 使用记录和递归差别联合
在设计函数式程序时,首先要考虑的是程序处理的数据;由于重要的程序都使用数据,因此,在应用程序设计中,这个方面极为重要。用函数语言实现程序,我们也是从设计在代码中用到的数据结构开始;下一步才会写处理数据的运算。
但是不同于面向对象的设计,它是把数据封装在对象的状态中;处理用方法表示,是对象的一部分,在运算中还可以和其他有关对象进行交互。而大多数函数式程序是以数据为中心的,因此,数据与运算明确分开。添加新的处理数据的运算,大体上就是写一个函数。
注意
以数据为中心、 以行为为中心程序(Data-centric and behavior-centric programs)
虽然,大多数函数式程序是以数据为中心的,但是,因为仍有一些应用程序和组件并不只考虑数据,它们关注的主要问题是行为。在使用滤镜批处理图像的应用程序中,主要的数据结构可能是滤镜列表,从函数的角度看,滤镜就是函数。
这表明,我们有两种主要方式看函数式代码,这些方法在一个应用程序的不同部分往往合组合在一起,但我们会分别讨论。在本章,我们讨论以数据为中心的程序,在第八章中我们将讨论以行为为中心的程序。
这一章的主要目的,是学会如何以函数方式思考应用程序的设计。我们会用一个应用程序环境演示,这个程序处理简单的文档,包含文本、图像和标题。在这一章,我们将使用 F# 作为主要语言。虽然在 C# 中也能使用函数风格编程,但是,以函数方式设计应用程序的整个结构,仍然有些不便,因为,函数式数据结构严重依赖数据类型,比如,差别联合。我们将会提到几个与面向对象相关的设计模式,亦会考虑如何在 C# 中处理不可变类型。
使用数据表示形式
在函数式编程中,通常使用多种数据结构来表示相同的程序数据。就是说,我们设计不同的数据结构,然后,可以在不同的表示形式之间进行转换,这些转换通常会计算出数据的其他信息。
针对不同的运算,使用不同的数据表示形式,可以更容易实现。在这一章,我们处理的文档有两种表示形式。在 7.2 节,我们会实现平面数据结构,它适合绘制文档;在 7.3 节,添加结构化的表示形式,它更适合存储和处理文档。这种方法还支持共享,因为,在不同表示形式上的运算,也可以由不同的开发人员独立地开发和维护,以进行一些扩展。
我们将首先讨论另一种 F# 类型,对于表示程序数据很重要,然后,会把注意力放到示例应用程序上。