Functions are central to functional programming. In Haskell, functions are first-class citizens, meaning they can be:
- Passed as arguments
- Returned as results
- Assigned to variables
- Stored in data structures
See also: Higher-Order Functions, Pattern Matching and Recursion, Polymorphism, Equational Reasoning
Function Definitions
Functions in Haskell can be defined in several ways:
Lambda (Anonymous) Functions
See: Lambda Calculus, Higher-Order Functions
\name -> "Hello, " ++ name
\n -> n + 5Named Functions with Equations
add x y = x + y
min x y = if x < y then x else yType Signatures
add :: Int -> Int -> Int
add x y = x + yCurrying
Haskell functions are “curried” by default, meaning they take one argument at a time and return a function that accepts the next argument.
See: Higher-Order Functions, Polymorphism
add :: Int -> (Int -> Int)
add x = \y -> x + yThis is equivalent to:
add :: Int -> Int -> Int
add x y = x + yBenefits of Currying
Currying enables partial application - supplying only some of the arguments to create a new function:
addFive :: Int -> Int
addFive = add 5
-- Usage:
addFive 10 -- Returns 15Function Application
Function application in Haskell doesn’t require parentheses around arguments:
f x y z -- Applies function f to arguments x, y, and zFunction application has the highest precedence:
f x * 2 -- Means (f x) * 2, not f (x * 2)Function Composition
The composition operator (.) combines functions:
See: Higher-Order Functions, Functors and Applicatives
(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = \x -> f (g x)This enables point-free style programming:
-- With explicit parameter
\x -> show (add10 x)
-- Point-free style
show . add10Equations are not Assignments
In imperative languages, we might write:
x = x + 1 // Modify x by adding 1
In Haskell, an equation like x = x + 1 is not an assignment; it’s a recursive definition that tries to define x as its successor, which would lead to an infinite loop.
Key Principles
- Variables in Haskell are immutable
- Equations establish mathematical relationships
- Once defined, a value cannot change
See: Expressions and Reduction, Equational Reasoning
Key Points to Remember
- All functions in Haskell take exactly one argument (currying makes multi-argument functions possible)
- Partial application is a powerful technique for creating specialized functions
- Function composition provides a way to combine functions elegantly
- Equations in Haskell define values; they don’t modify state
See: Pattern Matching and Recursion, Higher-Order Functions
Common Mistakes
- Confusing equations with assignments
- Misunderstanding function application precedence
- Forgetting to account for currying in type signatures