本文主要描述复合函数、λ表达式、高阶函数的一些基本概念以及它们之间的一些关系。示例代码将以Python作为主要编成语言。
首先简单地谈谈什么是函数。对于基本的面向过程以及函数式编程语言而言,可以直接用集合论中的函数概念加以描述。如果是面向对象的话,但使用朴素集合论中的函数概念去描述还显得不够,基本上要用到范畴(Category)论中的态射(Morphism)进行描述。而对于函数式编成语言而言,通过集合论的函数概念进行描述就显得更为适宜。
首先简单地介绍一下什么是函数。函数首先是一种关系。为了方便描述,后面将主要针对二元关系进行讲解,即可理解为一个输入,一个输出。
函数定义:设A和B是两个任意集合,f是从A到B的二元关系。若f具有性质:
(1)f的定义域Dom f = A,
(2)如果有(a1, b1), (a1, b2)属于f,那么b = b2, (注:a1属于集合A,b1、b2属于集合B)
则称关系f是从A到B的函数,记为f:A->B。
根据函数基本定义,我们下面可以举两个基本函数的例子:
在上述代码中,sum和mul都是函数。sum: Z->Z, mul: Z->Z,其中,Z为整数集。也就是参数x为整数,而返回值亦是整数。
有了函数的一个基本定义,那么后面我们可以容易地引入复合函数这一概念:
设g: A->B, f: B->C,定义复合函数f○g为:f○g={(a, c)| a属于A, c属于C,且存在b属于B,使b=g(a),c=f(b)},称f○g是从A到C的复合函数,记为f○g: A->C。对a属于A,有(f○g)(a) = f(g(a))。
根据定义描述,我们下面将举一个复合函数的例子。
上述代码中,compFunc在表现形式上可看作为:mul○sum。尽管mul和sum的输入和输出都是整数,不过为了方便描述,我们假定sum: A->B,mul: C->D,由于这里集合B是集合C的子集(各位可以思考一下如果假定集合C是集合B的子集是否可以),所以关系compFunc仍可构成函数关系。compFunc: A->D。
首先,A通过sum函数映射到B,然后B通过mul函数再映射到D,所以compFunc可表现为:mul(sum(a)),a为集合A的一个元素。
OK,有了基础概念之后我们就可以看看lambda表达式了。在函数式编成语言中,λ实际上就是指一个函数。不过它的一个特点就是,对于一个lambda而言,它所对应的是一个函数集中的某一个元素。我们看看下面一个简单的例子:
上述代码中,lambdaFunc的函数关系可被表达为:lambdaFunc: A->F,A是整数集,F是一个函数集。集合F的元素这里可记为:{λ1, λ2, ...}。其中,元素的下标为labmdaFunc的输入。
由于对于lambdaFunc中的lambda而言,这个lambda受到lambdaFunc输入参数n的制约。因此对于不同的输入n就会映射到F集中不同的lambda元素。而对于某一个函数lambdaε(ε为下标),lambdaε: B->C。lambda的输入参数x属于集合B,而其返回值则属于集合C。因此对于整个表达式lambdaFunc(10)(20)而言,就是(10属于A)通过lambdaFunc映射到(lambda(10)属于F);再由(20属于B)通过lambda(10)最后映射到(30属于C)。因此val的值就是30。
如果将lambdaFunc(10)抽象掉的话,即
那么aFunc实际上就可以视为一个复合函数:
这里,我们可以将lam(10)中的“10”视为:B->B这样的形式。
下面将描述高阶函数。
在《程序设计语言——实践之路》第二版汉化版中的第545页中讲述了高阶函数的概念:如果一个函数以函数作为实在参数,或者返回函数作为值,那么它就是一个高阶函数(high-order function),也称为函数形式。
下面的例子描述了一个比较简单的高阶函数:
我们来看一下HighOrderFunction:
HighOrderFunction: Ο->F,其中Ο表示空集,F为函数集lambda(f, g)。我们这里看到lambda(f, g)有两个输入参数,为了方便描述,我们将(f, g)作为一个关系对而看成一个输入源。设R为一个函数关系对集,(f, g)为其中一个元素,那么有lambda(f, g): R->G。设G为一个函数集,lambda(x)是其中一个元素。lambda(x): A->C。
我们可以看到高阶函数实际上隐藏了两个或两个以上的lambda。
下面给出完整的示例: