使用 F# 进行函数式编程入门 - 第二部分






3.10/5 (6投票s)
本文解释了函数式编程和 lambda 演算的基础知识。
背景
在本文的第一部分中,我解释了使用 F# 进行函数式编程的基础知识。在本节中,我将解释函数式编程的优点,并对过程式编程和函数式编程进行比较。最后,我将解释为什么 F# 和其他最流行的函数式语言不是纯粹的函数式语言。
函数式编程的优点
更贴近数学
如果您有数学背景,就会知道大多数计算机理论都深深植根于数学。虽然我们现在正处于快速应用程序开发(其中核心和重复的任务被抽象化)的趋势中,但我们在这些抽象之上找到了解决现实世界问题的方案。无论如何,问题解决都是基于数学的。数学的复杂程度和应用有助于找到更有效的解决方案。函数式编程更贴近数学。通过一组表示性语义(您可以在本文的第一部分中看到一些简单的示例),函数式语言可以比过程式语言更简单有效地解决问题。这种表示性语义使我们免受非终止的loop
语句、goto
和break
语句的困扰。
表达式求值无副作用
函数式语言的创建方式是为了模仿数学概念,因此表达式中的子表达式可以以任何顺序进行求值。这一特性使得函数式语言成为并行编程的选择。
参数化类型和函数
在第一部分的代码 4 中,您可以看到函数 square
需要一个函数作为参数,其表示性语义如下:
let square (f : int -> int) n = f(n) * f(n);;
像这样,所有类型和函数都是清晰参数化的,明确了需要输入什么以及将返回什么。这一特性使得代码更具通用性,意味着您可以将某个功能应用于不同的相关类型。
数量级短 O(n)
众所周知,数量级用于比较不同算法解决特定问题的性能,值越小,性能越高。与典型的过程式编程相比,理论上函数式编程中没有赋值。 (请参阅第一部分中的示例)。过程式程序包含 90% 的赋值语句。这是它们 O(n) 值高于函数式编程的主要原因。
真正的模块化编程
面向对象编程允许进行模块化编程,但是,通过参数化类型和非顺序属性的补充,可以使用函数式语言编写真正的模块化编程。您可以在第一部分的代码 4 中看到以模块化方式使用函数。
函数式编程在哪些方面超越了过程式编程?
令人惊讶的是,大多数过程式语言都具有一些函数式行为。函数式语言在哪些方面超越了过程式编程?让我们来看看。
- C、C++ 等过程式语言具有函数指针,我们可以将其视为高阶函数和柯里化函数。但是,这些函数指针非常有限,在这些语言中,您无法在没有任何名称的情况下动态创建函数。
- 这些过程式语言也支持递归。但是,这些仍然由顺序语句处理,就像人类与计算机交互一样。
Lambda 演算 - 函数式编程的起源
由于它更贴近数学,函数式编程的概念是基于数学的Lambda 演算。它是一种以更有效、更简单的方式表达任何类型算法的系统。通常,在数学和过程式语言中,函数必须被定义并由任意名称引用,例如
f(x) = { 0 如果 x = 0
x2 sin(1/x2) 如果 x ≠ 0 但在高阶函数中,对命名的坚持 rather inconsistent。
例如
定义 x 和 y 为 x = 2 且 y = 4,然后我们可以说 xx = y,这不需要给这个函数起任何名字。
在 lambda 演算中,函数可以匿名定义,它表达了函数对其参数的作用。Lambda 演算提供了一个符号 ? 来定义一个函数。例如,f(x) = x + 1 可以定义为 ?x.x+1。在这里,函数名和参数无关紧要,此函数 f(2) 的应用将是 (?x.x+1) 2。在此示例中,? 是函数,x 是参数,x+1 是函数体。
Lambda 演算的定义
如果 t 是一个 lambda 演算,那么如果
- t = x 其中 x 是变量
- t = ?x.M 其中 x 是变量,M 是 lambda 表达式
- t = MN 其中 M 和 N 是 lambda 表达式
函数应用是左结合的,例如 f x y = (f(x))(y)。简单来说,一个 lambda 演算只接受一个参数并应用它,然后返回一个结果。所有函数式语言的行为(递归、任意顺序求值、无状态)实际上是 lambda 演算的基本行为。
Lambda 演算中存在两种类型的变量:
- 绑定变量:这落入函数(或 lambda)的范围之内。
- 自由变量:这从函数体中的表达式中获取值。
例如,在 ?x.xy 中,x 是绑定变量,y 是自由变量。在编程语言中,我们分别称它们为参数或形参和局部变量。
为什么 F# 和其他流行的函数式语言不是纯粹的函数式语言
两个直接的原因是:
- 不变性:正如我们所学到的,不变的数据结构会导致性能问题。但是,对于集合类型,不变性比可变性要好得多。F# 就处于这个位置。
- 不适用的场合:函数式编程概念不适用于某些场景,例如 I/O 操作和 GUI。在这些领域,建议使用命令式风格。
摘要
在本部分中,我们学习了函数式语言的优点和基本概念。另外,请观看我关于使用 C# 3.0 进行函数式编程的两个部分的屏幕录像,网址为 http://www.screencast.com/t/a0lgbHiF7cF 和 http://www.screencast.com/t/dndqkp4r,或者,从 http://cid-1ea86c1fb1c134b8.skydrive.live.com/browse.aspx/ScreenCast 下载两者。
历史
- 2009 年 2 月 3 日:初始帖子