在Haskell中,用 . 函数来完成函数的组合,其定义如下
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \ x -> f (g x)
- f必须有一个与g的结果类型相同的值作为参数
函数组合的用途之一是动态地创建函数,并将其传递给其他函数。
当然,也可以使用Lambdas,但很多时候函数的组合更清晰、更简洁,如下
map (\ x negate (abs x)) [5, -3, -6.7, -3.2, -19.24]
map (negate.abs) [5, -3, -6.7, -3.2, -19.24]
函数的组合是向右结合的,所以可以同时组合几个函数。 f (g (z x))等价于(f.g.z) x,如下
map (\ xs -> negate (sum (tail xs))) [[1..5], [3..6], [1..7]]
map (negate . sum . tail) [[1..5], [3..6], [1..7]]
带有多个参数的函数,想使用函数组合,必须使用curry,让每个函数接受一个参数,如下
sum (replicate 5 (max 6.7 8.9))
(sum . replicate 5 . max 6.7) 8.9
sum. replicate 5 . max 6.7 $ 8.9
如果想要使用函数组合重写一个包含大量圆括号的表达式,可以先将最内层函数的最后一个形参放在$之后,然后开始组合所有其他函数
如下
replicate 100 (product (map (* 3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
replicate 100 . product . map (* 3) . zipWith max [1,2,3,4,5] $ [4,5,6,7,8]
有时函数的组合更容易阅读,有时函数的组合不容易阅读
追求短代码可以使用函数的组合,想提升阅读性可以使用let in表达式,如下
oddSquareSum = sum (takeWhile (< 10000) (filter odd (map (^ 2) [1..])))
oddSquareSum = sum . takeWhile (< 10000) . filter odd . map (^ 2) $ [1..]
oddSquareSum =
let oddSquares = filter odd $ map (^ 2) [1..]
belowLimit = takeWhile (< 10000) oddSquares
in sum belowLimit