Haskell基础9
Haskell基础9
扫描,$ 和函数组合
参考书籍: Learn you a Haskell
扫描
扫描,即指scanl和scanr函数。其与foldl和foldr类似,但是会将整个操作过程返回的所有值记录在一个列表中。比如:
1 | ghci> scanl (+) 0 [3,5,2,1] |
其中,scanl中最后的结果为列表的最后一个元素,scanr中为第一个元素。它可以用来跟踪折叠的执行过程。
$
$函数,也被称为函数应用符(function application operator)。他的定义如下:
1 | ($) :: (a -> b) -> a -> b |
看上去这个符号似乎没有任何意义。但是实际上因为$拥有最低的优先级,并且它是右结合的(一般的函数是左结合的),所以可以起到替代括号的作用。像下面的几种写法就是等价的:
1 | sqrt (3 + 5) |
$是右结合的,所以f $ g $ x和f $ ( g $ x )等价。因此,我们可以省去很多在最后的括号。
除了减少括号外,$还能够将函数应用转为函数,这就允许我们映射一个函数应用到一组函数组成的列表:
1 | ghci> map ($ 3) [(4+), (10*), (^2)] |
函数组合
定义
在数学中,函数组合(function composition)是这样定义的:$ (f g) (x) = f (g (x)) $。而在Haskell中的函数组合也与之类似,其符号为.。定义为: 1
2(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f ( g x )
在进行函数组合时,我们要确保函数g的返回值与f的参数类型相同。其使用很简单,我们可以用其将几个函数生成一个新函数:
1 | map (\x -> 3*x+1) |
带有多个参数的函数组合
对于带有多个参数的函数,当我们想要使用函数组合时,我们可以通过部分应用来时所有函数只剩下一个参数,然后再使用。如下面的几个式子便是等价的:
1 | sum (replicate 5 (max 6.7 8.9)) |
Point-Free 风格
函数组合的另一用途便是定义Point-Free风格,也称为Pointless风格。通过去掉函数定义中重复的变量,让代码更加简洁和易读。比如下面的代码:
1 | sum' xs = foldl (+) 0 xs |