Higher-Order Functions

-- Functions taking or returning functions
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
-- applyTwice (+ 3) 10 == 16
-- applyTwice ('h' :) "ey" == "hhey"

compose3 :: (c -> d) -> (b -> c) -> (a -> b) -> a -> d
compose3 f g h = f . g . h

flip' :: (a -> b -> c) -> b -> a -> c
flip' f y x = f x y

-- The big three
map (+ 1) [1, 2, 3]                      -- [2,3,4]
filter odd [1 .. 10]                     -- [1,3,5,7,9]
foldr (+) 0 [1 .. 10]                    -- 55

-- Other essentials
zipWith3 (\a b c -> a + b + c) [1, 2] [3, 4] [5, 6]   -- [9,12]
takeWhile (/= ' ') "hello world"         -- "hello"
iterate (`div` 2) 100 & takeWhile (> 0)  -- [100,50,25,12,6,3,1]
until (> 1000) (* 2) 1                   -- 1024
foldr (\x acc -> x : take 2 acc) [] [1 .. 10]  -- [1,2,3]
scanl (+) 0 [1, 2, 3, 4]                 -- [0,1,3,6,10] (running totals)
scanr (+) 0 [1, 2, 3]                    -- [6,5,3,0]
mapM_ print [1, 2, 3]                    -- run an action for each element (Module 20)

-- Building pipelines
wordFrequencies :: String -> [(String, Int)]
wordFrequencies =
  map (\ws -> (head ws, length ws))      -- safe: group never produces empty lists
    . group
    . sort
  
…