1. Bonus Tutorials : Lambda Expressions in Haskell - wimsio/universities GitHub Wiki
Table of Contents
1. Introduction to Lambda Expressions
Lambda expressions let you create functions without naming them. They are also known as anonymous functions.
In Haskell, functions are first-class citizens—they can be passed as arguments, returned, and stored in variables.
2. Lambda Syntax Basics
Basic Syntax:
\x -> expression
\
= “lambda” symbolx
= argument(s)->
= separates argument(s) from bodyexpression
= function body
Example:
\x -> x + 1
Try in GHCi:
(\x -> x + 1) 4
-- Output: 5
3. Lambda as Anonymous Functions
Lambdas are anonymous—they don’t need names.
Example:
map (\x -> x * 2) [1,2,3]
-- Output: [2,4,6]
4. Lambdas in Higher-Order Functions
A higher-order function takes or returns another function.
Example:
filter (\x -> x `mod` 2 == 0) [1..10]
-- Output: [2,4,6,8,10]
5. Currying and Partial Application
- Currying: All Haskell functions take one argument at a time.
- Partial Application: Apply a function to some arguments, getting back another function.
Example:
let add = \x -> \y -> x + y
add 2 3 -- Output: 5
let addTwo = add 2
addTwo 5 -- Output: 7
6. Advanced Lambda Techniques
6.1 Multiple Arguments
Lambdas can take several arguments:
(\x y -> x * y) 3 4
-- Output: 12
6.2 Nested Lambdas
Lambdas can return other lambdas:
(\x -> (\y -> x + y)) 2 3
-- Output: 5
6.3 Lambdas with Pattern Matching
Use patterns in lambda arguments. (For \case
, enable -XLambdaCase
with :set -XLambdaCase
.)
import Data.Maybe (mapMaybe)
map (\(a, b) -> a + b) [(1,2), (3,4)]
-- Output: [3,7]
Or using LambdaCase (GHC extension):
:set -XLambdaCase
let f = \case
[] -> "Empty list"
(x:xs) -> "Non-empty list"
f [] -- "Empty list"
f [1,2,3] -- "Non-empty list"
6.4 Point-Free Style
Remove explicit arguments:
map (\x -> x + 2) [1,2,3] -- [3,4,5]
map (+2) [1,2,3] -- [3,4,5]
7. Performance and Style Tips
- Use lambdas for short, local logic.
- Prefer named functions for complex tasks.
- Deeply nested lambdas can reduce readability.
- Lambdas aren’t always more efficient than named functions.
8. Deeper Real-World Lambda Examples
8.1 Sorting Complex Data
Sort a list of tuples by the second element:
import Data.List (sortBy)
let people = [("Alice", 30), ("Bob", 25), ("Carol", 27)]
let sortedByAge = sortBy (\(_, a1) (_, a2) -> compare a1 a2) people
sortedByAge
-- [("Bob",25),("Carol",27),("Alice",30)]
8.2 Transforming Data in Pipelines
Celsius to Fahrenheit:
let celsiusTemps = [0, 20, 30, 40]
let fahrenheitTemps = map (\c -> c * 9/5 + 32) celsiusTemps
fahrenheitTemps
-- [32.0,68.0,86.0,104.0]
8.3 Filtering Complex Conditions
Filter by salary:
let employees = [("Alice", 30000), ("Bob", 52000), ("Carol", 67000)]
let wellPaid = filter (\(_, salary) -> salary > 50000) employees
wellPaid
-- [("Bob",52000),("Carol",67000)]
8.4 Lambda with Fold (Reduce)
Sum only even numbers:
let numbers = [1..10]
let sumEvens = foldl (\acc x -> if even x then acc + x else acc) 0 numbers
sumEvens
-- 30
8.5 Working with Maybe/Just/Nothing
Extract and increment Just values:
import Data.Maybe (mapMaybe)
let values = [Just 1, Nothing, Just 3, Just 5, Nothing]
let incremented = mapMaybe (\mx -> case mx of Just x -> Just (x+1); Nothing -> Nothing) values
incremented
-- [2,4,6]
8.6 Composing Functions on the Fly
Capitalize words longer than 3 letters:
import Data.Char (toUpper)
let wordsList = ["cat", "elephant", "dog", "giraffe"]
let capitalized = map (\w -> if length w > 3 then map toUpper w else w) wordsList
capitalized
-- ["cat","ELEPHANT","dog","GIRAFFE"]
8.7 Using Lambdas with IO
Print each line with a number:
let linesList = ["Hello", "World", "Haskell"]
mapM_ (\(i, line) -> putStrLn (show i ++ ": " ++ line)) (zip [1..] linesList)
-- 1: Hello
-- 2: World
-- 3: Haskell
8.8 Lambdas for Event Handlers (GUI/Web)
Custom sort by string length:
import Data.List (sortBy)
let customSort = sortBy (\a b -> compare (length a) (length b))
customSort ["apple", "kiwi", "banana", "fig"]
-- ["fig","kiwi","apple","banana"]
9. Summary and Next Steps
- Lambda expressions make code concise and flexible.
- Essential for quick, local, or custom logic.
- Study related topics: function composition, advanced pattern matching, higher-order programming.
10. Glossary of Terms
Term | Meaning |
---|---|
Lambda expression | A function without a name (\x -> x + 1 ) |
Anonymous function | Another term for a lambda expression |
First-class citizen | Functions can be used like values |
Higher-order function | A function that takes or returns other functions |
Currying | Transforming a multi-argument function into a chain of single-argument ones |
Partial application | Giving some arguments to a function to get a new function |
Point-free style | Writing functions without explicit arguments |
Pattern matching | Using data structure patterns in function definitions |
GHCi | Interactive Haskell shell (REPL) |
REPL | Read-Eval-Print Loop, interactive environment |
Further Reading
- Learn You a Haskell For Great Good! – Lambdas
- Haskell Wiki: Lambda Calculus
- Real World Haskell: Higher-Order Functions