Functions & Recursion in Haskell
Functions are the building blocks of Haskell programs. Since Haskell is a purely functional language, functions are first-class citizens that can be passed as arguments, returned as results, and composed together.
Function Definition
Functions in Haskell are defined with a name, parameters, and an expression:
-- Simple function
add :: Int -> Int -> Int
add x y = x + y
-- Function with type signature
square :: Int -> Int
square x = x * x
Pattern Matching
Haskell allows pattern matching in function definitions:
-- Factorial with pattern matching
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)
-- Fibonacci sequence
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
Guards
Guards provide an alternative way to express conditional logic:
-- Absolute value with guards
absolute :: Int -> Int
absolute x
| x >= 0 = x
| otherwise = -x
-- Grade classifier
grade :: Int -> String
grade score
| score >= 90 = "A"
| score >= 80 = "B"
| score >= 70 = "C"
| score >= 60 = "D"
| otherwise = "F"
Lambda Functions
Anonymous functions can be created with lambda expressions:
-- Lambda function example
squareAll :: [Int] -> [Int]
squareAll xs = map (\x -> x * x) xs
-- Using lambda with filter
evens :: [Int] -> [Int]
evens xs = filter (\x -> x `mod` 2 == 0) xs
Higher-Order Functions
Functions that take other functions as arguments or return functions:
-- Function composition
compose :: (b -> c) -> (a -> b) -> a -> c
compose f g x = f (g x)
-- Applying a function twice
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
Recursion
Since Haskell doesn't have traditional loops, recursion is fundamental:
-- Sum of a list
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
-- Length of a list
length' :: [a] -> Int
length' [] = 0
length' (_:xs) = 1 + length' xs
-- QuickSort implementation
quickSort :: Ord a => [a] -> [a]
quickSort [] = []
quickSort (x:xs) =
quickSort [y | y <- xs, y <= x]
++ [x] ++
quickSort [y | y <- xs, y > x]
Tail Recursion
Tail-recursive functions are more efficient as they can be optimized:
-- Tail-recursive factorial
factorial :: Integer -> Integer
factorial n = helper n 1
where
helper 0 acc = acc
helper n acc = helper (n - 1) (acc * n)
-- Tail-recursive sum
sumList :: [Int] -> Int
sumList xs = helper xs 0
where
helper [] acc = acc
helper (x:xs) acc = helper xs (acc + x)
Function Composition
Functions can be composed using the (.) operator:
-- Composing functions
squareAndIncrement :: Int -> Int
squareAndIncrement = (+1) . (^2)
-- Multiple composition
processString :: String -> String
processString = reverse . map toUpper . filter (/= ' ')
← Previous: Introduction |
Next: Types & Typeclasses →