CodeToLive

Higher-Order Functions in Haskell

Higher-order functions are functions that take other functions as arguments or return functions as results. They are a fundamental concept in functional programming and enable powerful abstractions.

Functions as Arguments

Passing functions as arguments allows for flexible behavior:


-- Apply a function to a value twice
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)

-- Example usage
square x = x * x
increment x = x + 1

-- applyTwice square 2 → 16
-- applyTwice increment 5 → 7
      

Common Higher-Order Functions

Haskell's standard library includes many useful higher-order functions:


-- Map applies a function to each element
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs

-- Filter keeps elements that satisfy a predicate
filter :: (a -> Bool) -> [a] -> [a]
filter _ [] = []
filter p (x:xs)
  | p x       = x : filter p xs
  | otherwise = filter p xs

-- Fold (reduce) a list
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ acc [] = acc
foldr f acc (x:xs) = f x (foldr f acc xs)
      

Function Composition

The (.) operator composes functions:


-- Function composition operator
(.) :: (b -> c) -> (a -> b) -> a -> c
(f . g) x = f (g x)

-- Example usage
squareAndIncrement :: Int -> Int
squareAndIncrement = (+1) . (^2)

-- Multiple compositions
processString :: String -> String
processString = reverse . map toUpper . filter (/= ' ')
      

Partial Application

Functions can be partially applied to create new functions:


-- Partial application
add :: Int -> Int -> Int
add x y = x + y

addFive :: Int -> Int
addFive = add 5

-- Using partial application with map
incrementAll :: [Int] -> [Int]
incrementAll = map (+1)

-- Partial application with infix operators
multiplyBy :: Int -> Int -> Int
multiplyBy = (*)

doubleAll :: [Int] -> [Int]
doubleAll = map (multiplyBy 2)
      

Lambda Functions

Anonymous functions can be created with lambda syntax:


-- Lambda function examples
squareAll :: [Int] -> [Int]
squareAll = map (\x -> x * x)

filterEvens :: [Int] -> [Int]
filterEvens = filter (\x -> x `mod` 2 == 0)

-- Using lambda with fold
sumSquares :: [Int] -> Int
sumSquares = foldr (\x acc -> x * x + acc) 0
      

Function Currying

All Haskell functions are curried by default:


-- Curried function
multiply :: Int -> Int -> Int
multiply x y = x * y

-- Equivalent to:
multiply' :: Int -> (Int -> Int)
multiply' x = \y -> x * y

-- Can be partially applied
double :: Int -> Int
double = multiply 2

-- Calling with all arguments
result = multiply 3 4  -- 12
      

Flip and Other Combinators

Useful higher-order functions for function manipulation:


-- Flip argument order
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = f y x

-- Example usage
subtract' = flip (-)
-- subtract' 5 3 → 2 (same as 3 - 5)

-- Const function
const :: a -> b -> a
const x _ = x

-- Identity function
id :: a -> a
id x = x
      

Point-free Style

Point-free style omits variable names where possible:


-- With explicit variables
sumSquares xs = sum (map (^2) xs)

-- Point-free version
sumSquares = sum . map (^2)

-- Another example
countWords = length . words
      

Folding Lists

Folds are powerful higher-order functions for reducing lists:


-- Left fold (tail-recursive)
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl _ acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs

-- Right fold
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ acc [] = acc
foldr f acc (x:xs) = f x (foldr f acc xs)

-- Examples
sumList = foldr (+) 0
productList = foldl (*) 1
concatStrings = foldr (++) ""
      
← Previous: Pattern Matching | Next: Monads & IO →