Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

| 分类于 Program

| 0

| 阅读次数:

|

#### Curried functions

`Prelude> max 4 55Prelude> (max 4) 55`

`Prelude> let maxWithFour = max 4Prelude> maxWithFour 55`

partially applied 机制可以方便我们简单地实现动态地创建函数、将函数作为参数传入、用特定数据初始化函数等需求。

`let multThree x y z = x * y * z`

`multThree 3 5 9`，实际上的执行流程为 `((multThree 3) 5) 9`

• 将数字 3 传递给 `multThree`，它会返回一个函数 `(multThree 3)`。该函数接收任意两个数字，并计算它们和 3 的乘积
• 将数字 5 传递给 `(multThree 3)`，返回另一个函数 `((multThree 3) 5)`。该函数接收任意一个数字，并计算它和 15 的乘积
• 将数字 9 传递给 `((multThree 3) 5)`，返回 9 和 15 的乘积作为结果
`Prelude> let multThreeNums x y z = x * y * zPrelude> multThreeNums 2 3 424Prelude> let multTwoNumsWithNine = multThreeNums 9Prelude> multTwoNumsWithNine 2 354Prelude> let multOneNumWithEighteen = multTwoNumsWithNine 2Prelude> multOneNumWithEighteen 10180`

`Prelude> let divideByTen = (/10)Prelude> divideByTen 20020.0Prelude> (/10) 20020.0Prelude> 200 / 1020.0`

`divideByTen 200` 等同于 `(/10) 200` 等同于 `200 / 10`

`Prelude> let divideTen = (10/)Prelude> divideTen 25.0Prelude> (10/) 25.0Prelude> 10 / 25.0`

`Prelude> let isUpperAlphanum = (`elem` ['A'..'Z'])Prelude> isUpperAlphanum 'D'TruePrelude> isUpperAlphanum 'a'False`

#### 函数作为参数

`Prelude> let applyTwice f x = f (f x)Prelude> applyTwice (+3) 1016Prelude> applyTwice (++ " HAHA") "HEY""HEY HAHA HAHA"Prelude> applyTwice ("HAHA " ++) "HEY""HAHA HAHA HEY"Prelude> applyTwice (3:) [1][3,3,1]`
##### zipWith 的自定义实现
`zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]zipWith' _ [] _ = []zipWith' _ _ [] = []zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys`
`Prelude> :{Prelude| zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]ith' f Prelude| zipWith' _ [] _ = []Prelude| zipWith' _ _ [] = []Prelude| zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ysPrelude| :}Prelude>Prelude> zipWith' (+) [4,2,5,6] [2,6,2,3][6,8,7,9]Prelude> zipWith' (++) ["foo ", "bar ", "baz "] ["fighters", "hoppers", "aldrin"]["foo fighters","bar hoppers","baz aldrin"]Prelude> zipWith' (*) (replicate 5 2) [1..][2,4,6,8,10]`
##### flip 的自定义实现
`flip' :: (a -> b -> c) -> b -> a -> cflip' f y x = f x y`
`Prelude> :{Prelude| flip' :: (a -> b -> c) -> b -> a -> cPrelude| flip' f y x = f x yPrelude| :}Prelude>Prelude> flip' zip [1,2,3,4,5] "hello"[('h',1),('e',2),('l',3),('l',4),('o',5)]Prelude> zipWith (flip' div) [2,2..] [10,8,6,4,2][5,4,3,2,1]`

#### Maps & Filters

`map` 接收一个函数和一个列表作为参数，可以将函数应用到列表的每一项元素上。

`map` 函数的定义如下：

`map :: (a -> b) -> [a] -> [b]  map _ [] = []  map f (x:xs) = f x : map f xs`

`Prelude> map (+3) [1,5,3,1,6][4,8,6,4,9]Prelude> map (++ "!") ["BIFF", "BANG", "POW"]["BIFF!","BANG!","POW!"]Prelude> map (replicate 3) [3..6][[3,3,3],[4,4,4],[5,5,5],[6,6,6]]Prelude> map (map (^2)) [[1,2],[3,4,5,6],[7,8]][[1,4],[9,16,25,36],[49,64]]Prelude> map fst [(1,2),(3,5),(6,3),(2,6),(2,5)][1,3,6,2,2]`

`filter` 接收一个判断函数和一个列表作为参数，返回列表中所有使判断函数为真的元素。

`filter` 函数的定义如下：

`filter :: (a -> Bool) -> [a] -> [a]filter _ [] = []filter p (x:xs)    | p x       = x : filter p xs    | otherwise = filter p xs`

`Prelude> filter (>3) [1,5,3,2,1,6,4,3,2,1][5,6,4]Prelude> filter (==3) [1,2,3,4,5][3]Prelude> filter even [1..10][2,4,6,8,10]Prelude> let notNull x = not (null x) in filter notNull [[1,2,3],[],[3,4,5],[2,2],[],[],[]][[1,2,3],[3,4,5],[2,2]]Prelude> filter (`elem` ['a'..'z']) "u LaUgH aT mE BeCaUsE I aM diFfeRent""uagameasadifeent"Prelude> filter (`elem` ['A'..'Z']) "i lauGh At You BecAuse u r aLL the Same""GAYBALLS"`

`quicksort :: (Ord a) => [a] -> [a]quicksort [] = []quicksort (x:xs) =    let smallerSorted = quicksort (filter (<=x) xs)        biggerSorted = quicksort (filter (>x) xs)    in  smallerSorted ++ [x] ++ biggerSorted`

`largestDivisible :: (Integral a) => alargestDivisible = head (filter p [100000,99999..])    where p x = x `mod` 3829 == 0`

`map (*) [0..]`

`Prelude> let listOfFuns = map (*) [0..]Prelude> (listOfFuns !! 4) 520`

`!!` 函数可以从指定列表中根据索引值获取特定的元素。`(listOfFuns !! 4)` 即为 `(4*)`

#### Lambdas

Lambda 基本上是代码中只使用一次的匿名函数。
`\` 反斜杠符号指定参数，`->` 符号指定函数体。

`Prelude> zipWith (\a b -> a * b - 1) [5,4,3,2,1] [1,2,3,4,5][4,7,8,7,4]`

`Prelude> map (\(a,b) -> a + b) [(1,2),(3,5),(6,3),(2,6),(2,5)][3,8,9,8,7]`

Fold 有点类似于 `map` 函数，只不过 fold 操作最终会将列表中的元素归并（reduce）到单个值。

Fold 函数接收三个参数：

• binary function：接收两个参数的函数
• 初始值：称作累加器（accumulator）
• 需要被折叠的列表

binary function 继续接收刚返回的新 accumulator 和列表中剩余元素中的第一个作为参数，执行计算并返回新的 accumulator；

##### 左折叠 `foldl`

`Prelude> let sum' xs = foldl (\acc x -> acc + x) 0 xsPrelude> sum' [3, 5, 2, 1]11`

`let sum' = foldl (+) 0`

lambda 函数 `(\acc x -> acc + x)` 实际上等效于 `(+)`

`Prelude> let elem' y ys = foldl (\acc x -> if x == y then True else acc) False ysPrelude> elem' 2 [1, 2, 3]True`
##### 右折叠 `foldr`

`Prelude> let map' f xs = foldr (\x acc -> f x : acc) [] xsPrelude> map' (+3) [1, 2, 3][4,5,6]`

`maximum' :: (Ord a) => [a] -> amaximum' = foldr1 (\x acc -> if x > acc then x else acc)reverse' :: [a] -> [a]reverse' = foldl (\acc x -> x : acc) []product' :: (Num a) => [a] -> aproduct' = foldr1 (*)filter' :: (a -> Bool) -> [a] -> [a]filter' p = foldr (\x acc -> if p x then x : acc else acc) []head' :: [a] -> ahead' = foldr1 (\x _ -> x)last' :: [a] -> alast' = foldl1 (\_ x -> x)`

Learn You a Haskell for Great Good!