lambda
In Haskell, a lambda expression (anonymous function) lets you define a function inline without giving it a name. You write a backslash (\) followed by the parameters, then ->, then the body expression — for example, \x -> x + 1. Lambda expressions are especially useful when passing short logic to higher-order functions like map, filter, and foldr, or when you need a one-off transformation and a named function would be overkill.
Syntax
-- ----------------------------------------------- -- Basic lambda expression syntax -- ----------------------------------------------- -- Write an anonymous function inline using \parameter -> expression -- \x -> x + 1 takes x and returns x + 1 -- \x -> x * 2 takes x and returns x * 2 -- \x -> x ++ "!" appends "!" to a string and returns the result -- ----------------------------------------------- -- Lambda expressions with multiple parameters -- ----------------------------------------------- -- You can list multiple parameters after the backslash -- \x y -> x + y takes x and y and returns their sum -- \name rank -> "[" ++ rank ++ "] " ++ name -- ----------------------------------------------- -- Binding a lambda expression to a variable -- ----------------------------------------------- -- A lambda expression is a value and can be bound to a variable -- This is completely equivalent to a regular function definition -- addOne :: Int -> Int -- addOne = \x -> x + 1 -- binds \x -> x + 1 to addOne -- ----------------------------------------------- -- Passing a lambda to a higher-order function (most common use) -- ----------------------------------------------- -- Pass a lambda to map to transform every element -- map (\x -> x * 10) [1, 2, 3] -- [10, 20, 30] -- Pass a lambda to filter to keep only matching elements -- filter (\x -> x > 5) [3, 7, 2, 9, 4] -- [7, 9] -- ----------------------------------------------- -- Pattern matching on a tuple in a lambda parameter -- ----------------------------------------------- -- You can pattern match in the parameter position: \(a, b) -> a + b -- map (\(name, score) -> name ++ ": " ++ show score) pairs
Syntax reference
| Syntax | Description |
|---|---|
\x -> expr | A lambda expression (anonymous function) that takes parameter x. |
\x y -> expr | A lambda expression with two parameters x and y. It is curried. |
\(a, b) -> expr | A lambda expression that takes a tuple and pattern matches it inline. |
f = \x -> expr | Binds a lambda expression to the variable f. Equivalent to a regular function definition. |
map (\x -> expr) xs | Applies a lambda expression to every element of a list. |
filter (\x -> cond) xs | Keeps only the elements that satisfy the condition. |
foldr (\x acc -> expr) z xs | Folds a list from the right using an accumulator acc. |
Sample code
pp_lambda_basic.hs
-- pp_lambda_basic.hs — demonstrates lambda expression basics: definition, variable binding, and passing to higher-order functions
-- Uses PSYCHO-PASS characters to show the \x -> expr syntax
-- and how to pass lambdas to map and filter
--
-- Compile and run:
-- ghc pp_lambda_basic.hs -o pp_lambda_basic && ./pp_lambda_basic
module Main where
-- -----------------------------------------------
-- Sample data (name and crime coefficient)
-- -----------------------------------------------
-- List of (Inspector/Enforcer name, crime coefficient) pairs
inspectors :: [(String, Int)]
inspectors =
[ ("Tsunemori Akane", 12) -- Inspector — coefficient is always low
, ("Ginoza Nobuchika", 41) -- Inspector — calm and collected
, ("Kogami Shinya", 136) -- Enforcer — former detective
, ("Masaoka Tomomi", 116) -- Enforcer — veteran
, ("Kagari Shusei", 87) -- Enforcer — youngest member
]
-- -----------------------------------------------
-- Binding a lambda to a variable (equivalent to a regular function)
-- -----------------------------------------------
-- Adds the enforcement threshold (100) to a crime coefficient to compute an "alert level"
-- Regular definition: addThreshold x = x + 100
-- Bound lambda: addThreshold = \x -> x + 100
addThreshold :: Int -> Int
addThreshold = \x -> x + 100 -- binds the lambda to addThreshold
-- Prepends an "[Enforcer]" tag to a name
tagEnforcer :: String -> String
tagEnforcer = \name -> "[Enforcer] " ++ name -- binds the lambda to tagEnforcer
-- -----------------------------------------------
-- Using map with a lambda to transform every element
-- -----------------------------------------------
-- Multiplies each crime coefficient by 10 to produce a "potential risk" list
-- Lambdas are handy for short transformation functions like this
potentialRisks :: [(String, Int)]
potentialRisks = map (\(name, cc) -> (name, cc * 10)) inspectors
-- \(name, cc) -> pattern matches the tuple inline
-- Extracts just the names into a list
names :: [String]
names = map (\(name, _) -> name) inspectors
-- _ discards the unused element
-- -----------------------------------------------
-- Using filter with a lambda to select elements
-- -----------------------------------------------
-- Selects characters whose crime coefficient is >= 100 (enforcement level)
enforcers :: [(String, Int)]
enforcers = filter (\(_, cc) -> cc >= 100) inspectors
-- Selects characters whose crime coefficient is < 100 (inspector level)
clearInspectors :: [(String, Int)]
clearInspectors = filter (\(_, cc) -> cc < 100) inspectors
-- -----------------------------------------------
-- Output helper
-- -----------------------------------------------
printEntry :: (String, Int) -> IO ()
printEntry (name, cc) =
putStrLn $ padRight 22 name ++ " Crime coefficient: " ++ show cc
where
padRight n s = s ++ replicate (max 0 (n - length s)) ' '
-- -----------------------------------------------
-- Entry point
-- -----------------------------------------------
main :: IO ()
main = do
putStrLn "===== All characters ====="
mapM_ printEntry inspectors
putStrLn ""
putStrLn "===== Using a lambda bound to a variable ====="
-- Applies addThreshold to each crime coefficient
let thresholdList = map (\(name, cc) -> (name, addThreshold cc)) inspectors
mapM_ printEntry thresholdList
putStrLn ""
putStrLn "===== map: potential risk (coefficient × 10) ====="
mapM_ printEntry potentialRisks
putStrLn ""
putStrLn "===== filter: enforcement level (coefficient >= 100) ====="
mapM_ printEntry enforcers
putStrLn ""
putStrLn "===== filter: clear status (coefficient < 100) ====="
mapM_ printEntry clearInspectors
ghc pp_lambda_basic.hs -o pp_lambda_basic && ./pp_lambda_basic [1 of 1] Compiling Main ( pp_lambda_basic.hs, pp_lambda_basic.o ) Linking pp_lambda_basic ... ===== All characters ===== Tsunemori Akane Crime coefficient: 12 Ginoza Nobuchika Crime coefficient: 41 Kogami Shinya Crime coefficient: 136 Masaoka Tomomi Crime coefficient: 116 Kagari Shusei Crime coefficient: 87 ===== Using a lambda bound to a variable ===== Tsunemori Akane Crime coefficient: 112 Ginoza Nobuchika Crime coefficient: 141 Kogami Shinya Crime coefficient: 236 Masaoka Tomomi Crime coefficient: 216 Kagari Shusei Crime coefficient: 187 ===== map: potential risk (coefficient × 10) ===== Tsunemori Akane Crime coefficient: 120 Ginoza Nobuchika Crime coefficient: 410 Kogami Shinya Crime coefficient: 1360 Masaoka Tomomi Crime coefficient: 1160 Kagari Shusei Crime coefficient: 870 ===== filter: enforcement level (coefficient >= 100) ===== Kogami Shinya Crime coefficient: 136 Masaoka Tomomi Crime coefficient: 116 ===== filter: clear status (coefficient < 100) ===== Tsunemori Akane Crime coefficient: 12 Ginoza Nobuchika Crime coefficient: 41 Kagari Shusei Crime coefficient: 87
pp_lambda_multi.hs
-- pp_lambda_multi.hs — demonstrates multi-parameter lambda expressions and using lambdas with foldr
-- Uses PSYCHO-PASS characters to show the \x y -> expr form
-- and how to pass a lambda to foldr
--
-- Compile and run:
-- ghc pp_lambda_multi.hs -o pp_lambda_multi && ./pp_lambda_multi
module Main where
-- -----------------------------------------------
-- Sample data
-- -----------------------------------------------
-- List of (name, crime coefficient, psychological stability 0–100)
profiles :: [(String, Int, Int)]
profiles =
[ ("Tsunemori Akane", 12, 98) -- extremely stable
, ("Ginoza Nobuchika", 41, 72) -- slightly unstable
, ("Kogami Shinya", 136, 45) -- unstable
, ("Masaoka Tomomi", 116, 53) -- unstable
, ("Kagari Shusei", 87, 61) -- average
]
-- -----------------------------------------------
-- Lambda expression with multiple parameters
-- -----------------------------------------------
-- Calculates a "threat score" from a crime coefficient and stability value
-- Takes two arguments using the form \cc stability -> cc * 2 - stability
calcThreat :: Int -> Int -> Int
calcThreat = \cc stability -> cc * 2 - stability
-- For Kogami: 136 * 2 - 45 = 227
-- Takes a name and crime coefficient and returns a formatted display string
formatLine :: String -> Int -> String
formatLine = \name cc -> padRight 22 name ++ " Coeff: " ++ show cc
where
padRight n s = s ++ replicate (max 0 (n - length s)) ' '
-- -----------------------------------------------
-- Using foldr with a lambda to aggregate and rebuild a list
-- -----------------------------------------------
-- Sums the crime coefficients of all entries using foldr
-- Uses \(_, cc, _) acc -> cc + acc to process each element and accumulator
totalCriminalCoeff :: [(String, Int, Int)] -> Int
totalCriminalCoeff = foldr (\(_, cc, _) acc -> cc + acc) 0
-- Builds a list of names whose threat score is >= 100 using foldr
-- This combines the effect of filter + map in a single foldr pass
highThreatNames :: [(String, Int, Int)] -> [String]
highThreatNames = foldr step []
where
-- step receives each element and the accumulator
step (name, cc, stability) acc
| calcThreat cc stability >= 100 = name : acc -- high threat: prepend the name
| otherwise = acc -- low threat: skip
-- -----------------------------------------------
-- Output helper
-- -----------------------------------------------
printProfile :: (String, Int, Int) -> IO ()
printProfile (name, cc, stability) =
putStrLn $ padRight 22 name
++ " Coeff: " ++ padLeft 3 (show cc)
++ " Stability: " ++ padLeft 3 (show stability)
++ " Threat score: " ++ show (calcThreat cc stability)
where
padRight n s = s ++ replicate (max 0 (n - length s)) ' '
padLeft n s = replicate (max 0 (n - length s)) ' ' ++ s
-- -----------------------------------------------
-- Entry point
-- -----------------------------------------------
main :: IO ()
main = do
putStrLn "===== All profiles (with threat score) ====="
-- Uses the multi-parameter lambda calcThreat to display threat scores
mapM_ printProfile profiles
putStrLn ""
putStrLn "===== foldr: sum of crime coefficients ====="
let total = totalCriminalCoeff profiles
putStrLn $ " Total crime coefficient: " ++ show total
putStrLn ""
putStrLn "===== foldr: members with threat score >= 100 ====="
let highThreat = highThreatNames profiles
mapM_ (\name -> putStrLn $ " " ++ name) highThreat
putStrLn ""
putStrLn "===== Passing a multi-parameter lambda directly to map ====="
-- To use \name cc -> ..., you need currying
-- Here a tuple lambda is passed to map instead
let lines_ = map (\(name, cc, _) -> formatLine name cc) profiles
mapM_ putStrLn lines_
ghc pp_lambda_multi.hs -o pp_lambda_multi && ./pp_lambda_multi [1 of 1] Compiling Main ( pp_lambda_multi.hs, pp_lambda_multi.o ) Linking pp_lambda_multi ... ===== All profiles (with threat score) ===== Tsunemori Akane Coeff: 12 Stability: 98 Threat score: -74 Ginoza Nobuchika Coeff: 41 Stability: 72 Threat score: 10 Kogami Shinya Coeff: 136 Stability: 45 Threat score: 227 Masaoka Tomomi Coeff: 116 Stability: 53 Threat score: 179 Kagari Shusei Coeff: 87 Stability: 61 Threat score: 113 ===== foldr: sum of crime coefficients ===== Total crime coefficient: 392 ===== foldr: members with threat score >= 100 ===== Kogami Shinya Masaoka Tomomi Kagari Shusei ===== Passing a multi-parameter lambda directly to map ===== Tsunemori Akane Coeff: 12 Ginoza Nobuchika Coeff: 41 Kogami Shinya Coeff: 136 Masaoka Tomomi Coeff: 116 Kagari Shusei Coeff: 87
Overview
A Haskell lambda expression is an anonymous function written as \x -> x + 1. The backslash (\) is meant to resemble the Greek letter lambda (λ). Because a lambda expression is a value, you can bind it to a variable or pass it directly as an argument to a higher-order function. The regular function definition f x = expr and the lambda binding f = \x -> expr are completely equivalent. To accept multiple parameters, list them after the backslash: \x y -> x + y. This is curried, meaning it is identical to \x -> \y -> x + y. When the argument is a tuple, you can pattern match it inline: \(a, b) -> a + b. The most common use of lambda expressions is passing short transformation, filtering, or aggregation logic directly to higher-order functions such as map, filter, and foldr. They are particularly convenient for temporary functions that are not important enough to deserve their own name. For an overview of higher-order functions, see Higher-order functions (map / filter / foldr). For function composition syntax, see Function composition (. and $).
If you find any errors or copyright issues, please contact us.