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 + 5

Named Functions with Equations

add x y = x + y
min x y = if x < y then x else y

Type Signatures

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

Currying

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 + y

This is equivalent to:

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

Benefits 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 15

Function Application

Function application in Haskell doesn’t require parentheses around arguments:

f x y z  -- Applies function f to arguments x, y, and z

Function 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 . add10

Equations 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

  1. All functions in Haskell take exactly one argument (currying makes multi-argument functions possible)
  2. Partial application is a powerful technique for creating specialized functions
  3. Function composition provides a way to combine functions elegantly
  4. 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