max 4 5 = (max 4) 5
1. max는 값 4를 적용한다
2. 4를 적용하면 5를 적용하기 위한 또 다른 함수가 반환값이 된다
3. 반환됨 함수에 5를 적용한다
# multThree.hs
multThree :: Int -> (Int -> (Int -> Int))
multThree x y z = x * y * z
ghc> multThree 3 2 4
24
ghc> let multTwoWithNine = multThree 9
ghc> multTwoWithNine 2 3
54
# divideByTen.hs
divideByTen :: (Floating a) => a -> a
divideByTen = (/10)
ghc> divideByTen 200
20.0
# isUpperAlphanum.hs
isUpperAlphanum :: Char -> Bool
isUpperAlphanum = (`elem` ['A'..'Z'])
ghc> isUpperAlphanum 'C'
True
ghc> isUpperAlphanum 'z'
False
(subtract n)
처럼 subtract
함수를 사용해야 한다# applyTwice.hs
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
ghc> applyTwice (+3) 10
16
ghc> applyTwice (++ " HaHa") "Hey"
"Hey HaHa HaHa"
ghc> applyTwice (3:) [1]
[3,3,1]
# zipWith.hs
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
-- zipWith' :: (a -> a -> a) -> [a] -> [a] -> [a]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
ghc> zipWith' (+) [4, 2, 5, 6] [2, 6, 2, 3]
[6,8,7,9]
ghc> zipWith' max [6, 3, 2, 1] [7, 3, 1, 5]
[7,3,2,5]
ghc> zipWith' (++) ["foo", "bar"] [" fighters", " hoppers"]
["foo fighters","bar hoppers"]
ghc> zipWith' (zipWith' (*)) [[1,2,3], [3,5,6], [2,3,4]] [[3,2,2], [3,4,5], [5,4,3]]
[[3,4,6],[9,20,30],[10,12,12]]
# flip.hs
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f x y = f y x
{-
flip' f = g
where g x y = f y x
-}
ghc> flip' zip [1, 2, 3, 4, 5] "Hello"
[('H',1),('e',2),('l',3),('l',4),('o',5)]
ghc> zipWith (flip' div) [2, 2..] [10, 8, 6, 4, 2]
[5,4,3,2,1]
# map.hs
map' :: (a -> b) -> [a] -> [b]
map' _ [] = []
map' f (x:xs) = f x : map' f xs
ghc> map' (+3) [1, 5, 3, 1, 6]
[4,8,6,4,9]
ghc> map' (++ "!") ["BIFF", "BANG", "POW"]
["BIFF!","BANG!","POW!"]
# filter.hs
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' f (x:xs)
| f x = x : filter' f xs
| otherwise = filter' f xs
ghc> filter (> 3) [1, 5, 3, 2, 1, 6, 4, 3, 2, 1]
[5,6,4]
ghc> filter (== 3) [1, 5, 3, 2, 1, 6, 4, 3, 2, 1]
[3,3]
ghc> sum (takeWhile (< 10000) (filter odd (map (^2) [1..])))
166650
ghc> let listOfFuns = map (*) [0..]
ghc> (listOfFuns !! 4) 5 -- 리스트에서 4번쨰 요소를 꺼낸다
20
ghc> map (+3) [1, 6, 3, 2]
[4,9,6,5]
ghc> map (\x -> x + 3) [1, 6, 3, 2]
[4,9,6,5]
ghc> map (\(a,b) -> a + b) [(1,2), (6,3)]
[3,9]
# addThree.hs
addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z
addThree' :: Int -> Int -> Int -> Int
addThree' = \x -> \y -> \z -> x + y + z
ghc> addThree 2 3 5
10
ghc> addThree' 2 3 5
10
# flip.hs
flip' :: (a -> b -> c) -> (b -> a-> c)
flip' f = \x y -> f y x
ghc> map (flip' subtract 20) [1, 2, 3, 4]
[19,18,17,16]
# sum.hs
sum' :: (Num a) => [a] -> a
sum' xs = foldl (\acc x -> acc + x) 0 xs
ghc> sum' [3, 5, 2, 1]
11
# sum.hs
sum' :: (Num a) => [a] -> a
sum' = foldl (+) 0
ghc> sum' [3, 5, 2, 1]
11
(\acc x -> acc + x)
는 +
와 동일하다foldl (+) 0
호출은 리스틀 받는 함수를 반환할 것이기 떄문이다 (커리 적용)# map.hs
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x acc -> f x : acc) [] xs
ghc> map' (*2) [1, 2, 3, 4]
[2,4,6,8]
(*2)
는 리스트의 오른쪽에서부터 접근한다(*2)
를 적용하고 그 값을 []에 추가한다# map.hs
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldl (\acc x -> acc ++ [f x]) [] xs
++
함수는 :
보다 후러씨 느리기 때문에 어떤 리스트로 새로운 리스트를 만들 경우 보통 foldr을 사용한다# maximum.hs
maximum' :: (Ord a) => [a] -> a
maximum' = foldl1 max
ghc> maximum' [1,2,3,4,5]
5
ghc> scanl (+) 0 [3, 5, 2, 1]
[0,3,8,10,11]
ghc> scanr (+) 0 [3, 5, 2, 1]
[11,8,3,1,0]
ghc> scanl1 (\acc x -> if x > acc then x else acc) [3, 4, 5, 3, 7, 9, 2, 1]
[3,4,5,5,7,9,9,9]
ghc> scanl (flip (:)) [] [3, 2, 1]
[[],[3],[2,3],[1,2,3]]
f a b c
는 ` (((f a) b) c)`와 같다f $ g $ x
는 f $ (g $ x)
와 같다ghc> sum (filter (> 10) (map (*2) [2..10]))
80
ghc> sum $ filter (> 10) $ map (*2) [2..10]
80
ghc> map ($ 3) [(4+), (10*), (^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]
(f ◦ g)(x) = f(g(x))
와 같이 정의된다f (g (z x))
는 (f . g. z) x
와 같다ghc> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> f (g x)
ghc> map (\x -> negate (abs x)) [-5, -3, 6, -3, 2, 24]
[-5,-3,-6,-3,-2,-24]
ghc> map (negate . abs) [-5, -3, 6, -3, 2, 24]
[-5,-3,-6,-3,-2,-24]
ghc> map (\xs -> negate (sum (tail xs))) [[1..5], [3..6], [1..7]][-14,-15,-27]
ghc> map (negate . sum . tail) [[1..5], [3..6], [1..7]]
[-14,-15,-27]
ghc> sum (replicate 5 (max 6.7 8.9))
44.5
ghc> (sum . replicate 5) (max 6.7 8.9)
44.5
ghc> sum . replicate 5 $ max 6.7 8.9
44.5
ghc> replicate 2 (product (map (*3) (zipWith max [1,2] [4,5])))
[180,180]
ghc> replicate 2 . product . map (*3) $ zipWith max [1,2] [4,5]
[180,180]
ghc> fn x = ceiling (negate (tan (cos (max 50 x))))
ghc> fn = ceiling . negate . tan . cos . max 50
# oddSqureSum.hs
oddSquareSum :: Integer
oddSquareSum = sum (takeWhile (<10000) (filter odd (map (^2) [1..])))
ghc> oddSquareSum
166650
# oddSqureSum.hs
oddSquareSum' :: Integer
oddSquareSum' = sum . takeWhile (<10000) . filter odd $ map (^2)
[1..]
ghc> oddSquareSum'
166650