--"为什么要努力"
--“因为我喜欢的东西很贵, 我想去的地方很远, 我爱的人超完美"
妹纸周玥翻唱的“下课等你”,感觉比周杰伦本尊唱的更好呢。
柯里函数
虽然我们前面看到的很多函数都是带了非常多的参数的,而本质上,这些函数执行的过程是这样的:它不会一次性取完所有参数,而是在每次调用时只取一个参数,并返回一个一元函数来取下一次参数。e.g.
ghci> max 4 5
5
ghci> (max 4) 5
上面这个简单的栗子中,max函数并不会直接输入2个参数,而是先取参数4,并返回一个一元函数,再取5这个参数,得到最后的值。
所以,依次类推,其实很多参数的函数都是柯里函数。
再举个栗子感受下:
multThree :: Int -> Int -> Int -> Int
multThree x y z = x * y * z
由上面说的柯里函数的本质,我们通过传入少数参数来调用这个函数,并因此创建新的函数multiTwo:
ghci>let multiTwo = multThree 9
ghci>multiTwo 3 4
首先给multThree只传入一个参数9,让它返回一个新的函数multiTwo,这个multiTwo需要传入2个参数。简单的说,我们只要以部分的参数来调用某个 函数,就可以得到一个部分应用函数,这个新的部分应用函数需要传入的参数,要和前面少传入的参数一致。
这里需要注意的是,我们如果不给这个部分应用函数复值新的名字,直接打印这个部分应用函数在终端,就出错。
ghci>multThree 9
这里会打印出一堆错误信息
这里一定要理解这个部分应用函数的原理,所以,我也不断粗体它。
有关map和filter的栗子
比较实用的函数有:map,zipWith, flip, filter。
这里举一个非常巧妙地体现这些函数的栗子,涉及到了map和filter,非常非常意思。
克拉兹序列(Collatz sequence)
该序列产生的定义如下:
- 从任何自然数开始;
- 如果是1,停止;
- 如果是偶数,将它除以2;
- 如果是奇数,将它乘以3然后加1;
- 所得结果,然后重复上面算法;
从上面描述,我们最后会得到一个以1结尾的序列(列表),现在我们需要求解一个问题:分别以1和100之间的所有数做起始数,有多少个克拉兹序列的长度大于15?
第一步我们要写一个产生序列的函数:
chain :: Integer -> [Integer]
chain 1 = [1]
chain n
| even n = n : chain (n 'div' 2)
| ood n = n: chain (n*3 + 1)
这是一个标准的递归函数,这个函数会止步于1。
输入一个起始值10,来测试下该序列函数:
ghci> chain 10
[10, 5, 16, 8, 4, 2, 1]
接下来,计算有多少个长度大于15的序列?
numLongChains :: Int
numLongChains = length (filter isLong (map chain [1..100]))
where isLong xs = length xs > 15
这里需要解释下,filter 函数取一个谓词(也就是一个条件)和一个列表,返回该列表中符合该条件的元素组成的列表。map函数是取一个函数和列表作为参数,它会将这个函数应用到该列表中的每个元素,并产生一个新的列表。
所以,上面的函数numLongChains中,map把[1..100]的序列应用到了chain这个函数中,并返回一个生成了克拉兹序列的列表,这个含有克拉兹序列的列表又作为filter函数中的列表参数,isLong函数的实现在where语句中,它定义了一个谓词(也就是一个条件)length xs > 15, 也就是这个列表中要过滤出长度大于15的克拉兹序列,并返回这个满足条件的新的列表,最后这个新列表由length函数完成计算。
lambda
lambda函数就是一次性匿名的函数
有时候,我们需要传给高阶函数一些特定功能的函数,就跟上面这个栗子一样,isLong就是我们需要的特殊功能的函数,这样我们就会用到lambda。
要使用lambda,就写一个*(因为这样看起来它比较像希腊字母lambda),后面跟参数,多个参数之间用空格分隔开,-> 后面是函数体*。通常我们习惯将整个lambda函数用括号括起来。
所以上面numLongChains用lambda实现是这样的:
numLongChains :: Int
numLongChains = length (filter (\xs -> length xs >15) (map chain [1..100]))
这样不用额外再去定义一个函数名和实现。
以上。
贴出周玥小妹妹的照片:
![](https://img.haomeiwen.com/i2010339/349ab4cfef8fb3ad.jpg)
![](https://img.haomeiwen.com/i2010339/115eccd66818cf67.gif)
网友评论