65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.33/5 (9投票s)

2009年2月3日

CC (ASA 2.5)

3分钟阅读

viewsIcon

53307

本文解释了函数式编程的基础知识。

引言

在本文中,我将解释函数式编程背后的基本概念以及这些语言相对于过程式编程的优势。

什么是过程式编程?

通常,我们将过程式编程称为“命令式”,意思是指定程序应采取的步骤以实现结果。 从数学上讲,通过语句和表达式修改变量的值,例如

Mathematical expression of procedural programming

请参见以下代码片段

// Code 1
int i = 0;
i = Convert.ToInt32(Console.ReadLine());
i = i + 10;

变量及其值使过程式编程成为基于“状态”的编程,意味着从输入状态更改为输出状态。 在这里,输出是确定性的,因为

deterministic output

其中,f是一个函数。

简单地说,我们可以说,过程式编程包含以下类型的语句

  • Sequential
  • Conditional
  • 重复

什么是函数式编程?

在本节中,让我们首先了解函数式编程与过程式编程的不同之处。

变量是值

函数式编程中没有状态机制,也就是说变量被认为是值。

序列是无意义的

在函数式编程中,顺序语句是无意义的,这意味着没有重复的语句。 而是,它提供了一种称为递归的机制,意味着函数调用自身。 例如,让我们编写一个程序来计算过程式编程和函数式编程中给定范围的总和。

// Code 2
// Sum of range in C# (Procedural)
int SumOf(int fromValue, int toValue)
{
    int result = 0;
    for(int i = fromValue; i <= toValue; i++)    
        result += i;
    return result;
}

上面的过程式程序使用状态resulti给出一个确定性的输出。 让我们看一下函数式编程代码。

// Code 3
//Sum of range in F# (Functional)
#light
let rec SumOf fromValue toValue =   
    if fromValue > toValue then 0 else (SumOf (fromValue + 1) toValue) + fromValue

在上面的函数式程序中,您可以看到递归方法的强大功能,并且变量被视为值。 上述程序中显示的递归在包括C++、C#和Java在内的现代过程式语言中是可行的。 但是,我将在后面的章节中展示它在函数式编程中的真正好处。

函数是值

函数可以像值一样处理,因此您可以将它们作为参数传递,作为函数值返回并与其他人一起计算(这在代码3中显示)。

不可变的数据结构

我们知道,不可变意味着对象的创建后,其状态不能被修改。 在.NET中,string是这方面的一个很好的例子。 不可变性使程序变得更加简单,因为不需要执行复制和比较。 但是,在现实世界的编程中,所有对象都不可变是没有意义的。 这会影响系统性能。 从纯函数式角度来看,对象是不可变的。 让我们在后面的章节中找到函数式编程实现如何处理这个问题。

让我们考虑一个不可变的集合,每次向其中添加一个项目时,根据理论,都会创建一个新对象。 因此,要将四个整数添加到不可变集合MyList

MyList result = new MyList().Add(100).Add(101).Add(102);

这实际上意味着

MyList l0 = new MyList();
MyList l1 = l0.Add(100);
MyList l2 = l1.Add(101);
MyList result = l2.Add(102);

高阶函数

接受另一个函数作为参数的函数称为高阶函数。 让我们看一个 F# 中的高阶示例。

// Code 4
//High order function example in F# (Functional)
#light
let rec factorial n = if n <= 1 then 1 else n * factorial (n-1);;
let square (f : int -> int) n = f(n) * f(n);;
System.Console.WriteLine(square factorial 3); // 36

函数square需要一个以整数作为参数并返回一个整数的函数,以及n。此函数将f应用于n然后计算平方。

柯里化函数

将其结果返回为函数的函数称为柯里化。 让我们看一个 F# 中的柯里化示例。

// Code 5
//Curried function example in F# (Functional)
#light
let rec XPowerN x n =
    match n with
    | 0 -> 1
    | n -> x * XPowerN x (n-1);;
let Square x= XPowerN x 2;;
let Cube x = XPowerN x 3;;
System.Console.WriteLine(Square 4); 	// 16
System.Console.WriteLine(Cube 2); 	// 8

代码 5 显示 XPowerN 在函数 SquareCube 中被柯里化。

结束语

在本节中,我们已经了解了什么是函数式编程以及它与过程式编程的不同之处。 在下一部分中,我将解释函数式编程的起源λ演算以及函数式编程的优势。

阅读本文的第二部分

参考文献

http://www.screencast.com/t/a0lgbHiF7cFhttp://www.screencast.com/t/dndqkp4r 观看我的关于 C# 3.0 函数式编程的两部分屏幕广播,或者从 http://cid-1ea86c1fb1c134b8.skydrive.live.com/browse.aspx/ScreenCast 下载。

历史

  • 2009 年 2 月 3 日:初始帖子
© . All rights reserved.