Haskell 学习笔记 (2)
- 高阶函数就是以函数为参数或者返回值的函数。
- 柯里函数
lambda
函数map
,filter
compareWithHundred :: Int -> Ordering
compareWithHundred = compare 100
divideByTen :: (Floating a) => a -> a
divideByTen = (/10)
dividedByTen :: (Floating a) => a -> a
dividedByTen = (10/)
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
flip' :: (a -> b -> c) -> b -> a -> c
flip' f y x = f x y
map' :: (a -> b) -> [a] -> [b]
map' _ [] = []
map' f (x:xs) = f x : map' f xs
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' p (x:xs)
| p x = x : filter' p xs
| otherwise = filter' p xs
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let le = filter (<=x) xs
gt = filter (> x) xs
in quicksort le ++ [x] ++ quicksort gt
takeWhile' :: (a -> Bool) -> [a] -> [a]
takeWhile' _ [] = []
takeWhile' p (x:xs)
| p x = x : takeWhile' p xs
| otherwise = []
zipWith (\a b -> (a*30+3)/b) [5,4..1] [1..5] -- [153.0,61.5,31.0,15.75,6.6]
map (\(a, b) -> a+b) [(1,2), (3,5), (6,2), (2,6), (2,5)] -- [3,8,8,8,7]
addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z
addThree' :: Int -> Int -> Int -> Int
addThree' = \x -> \y -> \z -> x + y + z
flip'' :: (a -> b -> c) -> b -> a -> c
flip'' f = \x y -> f y x
foldl
foldl
从列表的左端开始折叠,用初始值和列表的头部调用二元函数,得到一个新的累加值,并用新的累加值与列表的下一个元素调用二元函数,以此类推。foldl
的二元函数,第一个参数是累计值,第二个参数是当前列表值foldl f w [x y z] -- f (f (f w x) y) z
foldr
foldr
从列表的有段开始折叠foldr
的二元函数,第一个参数是当前列表值,第二个参数是累计值foldr f w [x y z] -- f x (f y (f z w))
foldr
可以用来处理无限长度列表- 需要生成新列表的时候,一般倾向于使用
foldr
foldl1
,foldr1
foldl1
,foldr1
与foldl
,foldr
相似,只是无须明确提供初始值。它们假定列表的第一个(最后一个)元素为初始值。
scanl
,scanr
,scanl1
,scanr1
和上述函数类似,只是保存了每次累加值的变动
sum' :: (Num a) => [a] -> a
sum' xs = foldl (+) 0 xs
-- equal to: sum' xs = foldl (\acc x -> acc + x) 0 xs
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x acc -> f x : acc) [] xs
-- Less efficient: map' f xs = foldl (\acc x -> acc ++ [f x]) [] xs
reverse' :: [a] -> [a]
reverse' = foldl (\acc x -> x : acc) []
-- equal to: reverse' = foldl (flip (:)) []
product' :: (Num a) => [a] -> a
product' = foldl (*) 1
foldl (-) 0 [1,2,3,4,5] -- -15 = ((((0-1)-2)-3)-4)-5
foldr (-) 0 [1,2,3,4,5] -- 3 = 1-(2-(3-(4-(5-0))))
and' :: [Bool] -> Bool
and' xs = foldr (&&) True xs
and (repeat False) -- False = False && (False && (False && ...))
maximum' :: (Ord a) => [a] -> a
maximum' = foldl1 max
scanl (-) 0 [1,2,3,4,5] -- [0,-1,-3,-6,-10,-15]
scanr (-) 0 [1,2,3,4,5] -- [3,-2,4,-1,5,0]
$
成为函数应用符$
优先级最低,空格的函数调用是左结合的,$
是右结合的$
可将函数应用转为函数.
称为函数组合.
右结合Point-Free
风格
($) :: (a -> b) -> a -> b
f $ x = f x
sum (filter (> 10) (map (*2) [2..10])) -- 80
sum $ filter (> 10) (map (*2) [2..10]) -- 80
sum $ filter (> 10) $ map (*2) [2..10] -- 80
map ($ 3) [(4+), (10*), (^2), sqrt] -- [7.0,30.0,9.0,1.732050807569]
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
map (\x -> negate (abs x)) [5,-3,-6,7] -- [-5,-3,-6,-7]
map (negate . abs) [5,-3,-6,7] -- [-5,-3,-6,-7]
map (negate . sum . tail) [[1..5],[3..6],[1..7]] -- [-14,-15,-27]
sum (replicate 5 (max 6.7 8.9)) -- 44.5
(sum . replicate 5) (max 6.7 8.9) -- 44.5
sum . replicate 5 $ max 6.7 8.9 -- 44.5
replicate 2 (product (map (*3) (zipWith max [1,2] [4,5]))) -- [180,180]
replicate 2 . product . map (*3) $ zipWith max [1,2] [4,5] -- [180,180]
fn x = ceiling (negate (tan (cos (max 50 x))))
fn' = ceiling . negate . tan . cos . max 50
oddSquareSum :: Integer
oddSquareSum = sum (takeWhile (<10000) (filter odd (map (^2) [1..])))
oddSquareSum' :: Integer
oddSquareSum' = sum . takeWhile (<10000) . filter odd $ map (^2) $ [1..]