In [1]:
-- haskell函数只能接收一个参数,多参数函数使用柯里化实现
max 4 5
In [2]:
(max 4) 5
In [3]:
:t max
In [4]:
multithree :: Int -> Int -> Int -> Int
multithree x y z = x * y * z
In [5]:
-- equals
multithree 3 5 9
In [6]:
((multithree 3) 5) 9
In [7]:
-- 返回一个函数,类似python partial
let multTwoWithNine = multithree 9
In [8]:
multTwoWithNine 2 3
In [10]:
compareWithHundred :: Int -> Ordering
compareWithHundred x = compare 100 x
In [11]:
compareWithHundred 99
In [13]:
-- equals above
compareWithHundred :: Int -> Ordering
compareWithHundred = compare 100
In [14]:
compareWithHundred 89
In [15]:
-- 通过截断对中缀函数部分应用
divideByTen :: (Floating a) => a -> a
divideByTen = (/10)
In [16]:
divideByTen 200
In [17]:
(/10) 200
In [18]:
-- -需要使用subtract替代
(subtract 4) 5
In [19]:
-- 打印函数, 默认函数不支持Show, 打印回报错
-- this would raise
-- multithree 4 3
In [21]:
-- 接收函数的函数
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
In [22]:
applyTwice (+3) 10
In [23]:
applyTwice (++ " HAHA") "HEY"
In [24]:
applyTwice (3:) [1]
In [30]:
-- 实现zipwith
zipwith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipwith' _ [] _ = []
zipwith' _ _ [] = []
zipwith' f (x:xs) (y:ys) = f x y : zipwith' f xs ys
In [31]:
zipwith' (+) [4, 2, 5, 6] [2, 6, 2, 3]
In [32]:
zipwith' max [6, 3, 2, 1] [7, 3, 1]
In [34]:
zipwith' (*) (replicate 5 2) [1..]
In [35]:
-- 实现flip
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = g
where g x y = f y x
In [36]:
-- same as above
flip' f x y = f y x
In [37]:
zip [1..5] "hello"
In [39]:
flip' zip [1..5] "hello"
In [40]:
zipWith div [2, 2..] [10, 8, 6, 4, 2]
In [41]:
zipWith (flip' div) [2, 2..] [10,8..2]
In [42]:
-- 函数式编程工具箱
-- map函数
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x: map f xs
In [43]:
map (+3) [1,5,1,3,1,6]
In [45]:
map (++ "!") ["BIFE", "BANS", "BANG", "POW"]
In [46]:
map (replicate 3) [3..6]
In [48]:
map (map (^2)) [[1, 2], [3, 4, 5, 6], [7, 8]]
In [50]:
map fst [(1, 2), (3, 5), (6, 3), (2, 6), (2, 5)]
In [52]:
-- fliter函数
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
In [54]:
filter (>3) [1, 5, 3, 2, 1, 6, 4, 3, 2, 1]
In [55]:
filter (==3) [1..5]
In [56]:
filter even [1..10]
In [57]:
let notNull x = not (null x) in filter notNull [[1, 2, 3], [], [3,4,5], [2, 2], [], [], []]
In [58]:
filter (`elem` ['a'..'z']) "u LaUgH aT mE BeCaUsE I aM diFfeRent"
In [59]:
filter (`elem` ['A'..'Z']) "i LaUgH aT mE BeCaUsE I aM"
In [60]:
-- 列表推导有时更好用
filter (< 15) (filter even [1..20])
In [61]:
[x | x <- [1..20], x < 15, even x]
In [65]:
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smaller = filter (<= x) xs
larger = filter (> x) xs
in quicksort smaller ++ [x] ++ quicksort larger
In [68]:
-- more `map` and `filter`
largestDivible :: Integer
largestDivible = head (filter p [100000, 99999..])
where p x = x `mod` 3829 == 0
In [70]:
takeWhile (/=' ') "elephants know how to party"
In [71]:
sum (takeWhile (<10000) (filter odd (map (^2) [1..])))
In [72]:
-- same as above
sum (takeWhile (<10000) [m | m<- [n^2 | n<- [1..]], odd m])
In [75]:
-- 克拉数
chain :: Integer -> [Integer]
chain 1 = [1]
chain n
| even n = n:chain (n `div` 2)
| odd n = n:chain (n*3 + 1)
In [76]:
chain 10
In [77]:
chain 1
In [78]:
chain 30
In [79]:
let listOfFuns = map (*) [0..]
(listOfFuns !! 4) 5
In [81]:
-- lambda 匿名函数
numLongChains :: Int
numLongChains = length (filter (\xs -> length xs > 15) (map chain [1..100]))
In [82]:
map (+3) [1,6,3,2]
In [83]:
map (\x -> x + 3) [1, 6,3,2]
In [85]:
zipWith (\a b -> (a * 30 + 3) / b) [5, 4, 3, 2, 1] [1,2,3,4,5]
In [86]:
map (\(a, b) -> a + b) [(1, 2), (3, 5), (6, 3), (2, 6), (2, 5)]
In [87]:
addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z
In [88]:
addThree' :: Int -> Int -> Int -> Int
addThree' = \x -> \y -> \z -> x + y + z
In [89]:
flip' :: (a -> b -> c) -> b -> a -> c
flip' f = \x y -> f y x
In [90]:
zipWith (flip (++)) ["love you", "love me"] ["i ", "you "]
In [92]:
map (flip subtract 20) [1, 2, 3, 4]
In [93]:
-- 折叠fold
sum' :: (Num a) => [a] -> a
sum' xs = foldl (\acc x -> acc + x) 0 xs
In [94]:
sum' [3, 5, 2,1]
In [95]:
-- same as above
sum' :: (Num a) => [a] -> a
sum' = foldl (+) 0
In [96]:
sum' [3..7]
In [97]:
-- fold right
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x acc -> f x : acc ) [] xs
In [98]:
map' (+3) [1,2,3]
In [99]:
-- fold left
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldl (\acc x -> acc ++ [f x]) [] xs
In [100]:
map' (+3) [1, 2, 3]
In [101]:
-- 生成列表有右fold更好
-- 左折叠无法处理无限列表,右折叠可以
elem' :: (Eq a) => a -> [a] -> Bool
elem' y ys = foldr (\x acc -> if x == y then True else acc) False ys
In [103]:
elem' False [False, True]
In [104]:
-- foldl1 foldr1
maximum' :: (Ord a) => [a] -> a
maximum' = foldl1 max
In [106]:
-- fold reverse
reverse' :: [a] -> [a]
reverse' = foldl (\acc x -> x : acc) []
In [107]:
reverse' [1..5]
In [108]:
reverse' :: [a] -> [a]
reverse' = foldl (flip (:)) []
In [109]:
product' :: (Num a) => [a] -> a
product' = foldl (*) 1
In [110]:
product' [1..5]
In [111]:
filter' :: (a -> Bool) -> [a] -> [a]
filter' p = foldr (\x acc -> if p x then x : acc else acc) []
In [112]:
filter' (>3) [1..5]
In [114]:
last' :: [a] -> a
last' = foldl1 (\_ x -> x)
In [115]:
last' [1..5]
In [117]:
and' :: [Bool] -> Bool
and' xs = foldr (&&) True xs
In [118]:
and' [True, False, True]
In [119]:
and' (repeat False)
In [120]:
-- 扫描scan, 跟踪fold实现过程
scanl (+) 0 [3,5,2,1]
In [121]:
scanr (+) 0 [3, 5,2,1]
In [122]:
-- scan to see over fold
sqrtSums :: Int
sqrtSums = length (takeWhile (<1000) (scanl1 (+) (map sqrt [1..]))) + 1
In [123]:
sqrtSums
In [132]:
sqrtSums :: [Float]
sqrtSums = takeWhile (<1000) (scanl1 (+) (map sqrt [1..]))
In [133]:
sqrtSums
In [135]:
-- 函数应用符号 $
($) :: (a -> b) -> a -> b
f $ x = f x
In [136]:
sqrt 3 + 4 + 9
In [137]:
sqrt $ 3 + 4 + 9
In [138]:
sum (filter (> 10) (map (*2) [2..10]))
In [139]:
sum $ filter (>10) (map (*2) [2..10])
In [141]:
-- good usage。 函数是同类型
map ($ 3) [(4+), (10*), (^2), sqrt]
In [143]:
-- 函数组合,用来生产新函数
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
In [146]:
map (\x -> negate (abs x)) [5,-3,-6,7,-3,12,-19,24]
In [147]:
map (negate . abs) [5,-3,-6,7,-3,12,-19,24]
In [149]:
map (negate . sum . tail) [[1..5], [3..6], [1..7]]
In [151]:
-- 多参数函数组合, 通过部分应用转化为单参数函数
sum (replicate 5 (max 6.7 8.9))
In [153]:
(sum . replicate 5) (max 6.7 8.9)
In [154]:
-- pointless 风格
fn x = ceiling (negate (tan (cos ( max 50 x))))
In [4]:
fn = ceiling . negate . tan . cos . max
In [3]:
-- 不推荐过程的pointless风格代码。推荐使用let保存中间结果