- How to read a function type such as f:A→Bf: A \rightarrow Bf:A→B.
- Why functions can be treated as first-class objects.
- What happens when a function is applied to one or more arguments.
- How partial application and function composition build new functions from existing ones.
A programming paradigm is a style of programming: a set of ideas about how programs should be structured. In the functional programming paradigm, computation is mainly described by evaluating functions and combining functions.
This topic is mostly about the notation AQA expects you to recognise and use. You do not need to learn a particular functional language here; focus on the mathematical ideas behind functions.
Function type
A function fff has a type written f:A→Bf: A \rightarrow Bf:A→B. This means the function takes an input from set AAA and returns an output from set BBB. The type itself is A→BA \rightarrow BA→B.
The set AAA is the argument type. It is also called the domain: the set from which input values are chosen.
The set BBB is the result type. It is also called the co-domain: the set from which output values are chosen.
A data type is a category of values, such as integer, character, Boolean or string. The domain and co-domain are always subsets of objects in some data type. For example, the set of lowercase letters is a subset of character values, and the set {0,1,2,…,25}\{0,1,2,\dots,25\}{0,1,2,…,25} is a subset of integer values.
A function does not have to use every value in its co-domain. It only needs to return values that belong to the co-domain.
The diagram shows a function from a domain to a co-domain, and also previews how two functions can be composed later in this topic.

Domain versus co-domain
The domain is where inputs come from. The co-domain is where outputs are allowed to come from. Not every co-domain value must actually be produced.
For example, suppose:
f:{a,b,c,…,z}→{0,1,2,…,25}f: \{a,b,c,\dots,z\} \rightarrow \{0,1,2,\dots,25\}f:{a,b,c,…,z}→{0,1,2,…,25}
with the rule that a↦0a \mapsto 0a↦0, b↦1b \mapsto 1b↦1, and so on. Here the input values are letters, and the output values are integers from 0 to 25.
Finding a function type
A function lengthOfWord takes one lowercase word and returns the number of characters in it. Assume the longest allowed word has 20 characters.
- Choose the domain by identifying the possible inputs: the input is one lowercase word, so the domain is a set of lowercase strings.
- Choose the co-domain by identifying the allowed outputs: the output is a whole number from 0 to 20, so the co-domain is {0,1,2,…,20}\{0,1,2,\dots,20\}{0,1,2,…,20}.
- Write the function type using arrow notation: lengthOfWord:lowercaseString→{0,1,2,…,20}\text{lengthOfWord}: \text{lowercaseString} \rightarrow \{0,1,2,\dots,20\}lengthOfWord:lowercaseString→{0,1,2,…,20}.
Confusing co-domain with actual outputs
Do not assume the co-domain is exactly the set of values that will be produced. It is the set of values that may be used as outputs.
First-class object
A first-class object is a value that may appear in expressions, be assigned to a variable, be passed as an argument, and be returned from a function call.
In many languages, integers, floating-point values, characters and strings are first-class objects. In functional programming languages, functions are also first-class objects.
Some imperative programming languages also support first-class functions. An imperative programming language is one where programs are mainly written as sequences of commands that update state. If such a language supports first-class functions, a function can be handled like other values.
This means a function can be:
- stored in a variable;
- passed into another function;
- returned as the result of a function call;
- used in an expression.
A function that takes another function as an argument, or returns a function, is often called a higher-order function.
Passing a function as an argument
Suppose double is a function where double(n)=n×2\text{double}(n) = n \times 2double(n)=n×2, and applyTwice is defined as applyTwice(functionValue,x)=functionValue(functionValue(x))\text{applyTwice}(functionValue, x) = functionValue(functionValue(x))applyTwice(functionValue,x)=functionValue(functionValue(x)).
- Pass the function
double as the first argument and 5 as the second argument: applyTwice(double,5)\text{applyTwice}(\text{double}, 5)applyTwice(double,5).
- Apply the inner function call first: double(5)=10\text{double}(5) = 10double(5)=10.
- Apply the function again to the result: double(10)=20\text{double}(10) = 20double(10)=20.
- Therefore, treating
double as a first-class object allows applyTwice to return 20.
Spotting first-class functions
If a function is being passed around like data, stored in a variable, or returned by another function, it is being treated as a first-class object.
Function application
Function application means giving particular argument values to a function.
For example, add(3,4)\text{add}(3,4)add(3,4) is the application of the function add to the integer arguments 3 and 4.
A two-argument function can be described using the Cartesian product. The Cartesian product of two sets is the set of all ordered pairs formed by taking one value from each set.
So the type of add can be written as:
add:integer×integer→integer\text{add}: \text{integer} \times \text{integer} \rightarrow \text{integer}add:integer×integer→integer
Although we usually say add takes two arguments, formally this version takes one argument that is a pair, such as (3, 4).
Applying a function to a pair
Let add:integer×integer→integer\text{add}: \text{integer} \times \text{integer} \rightarrow \text{integer}add:integer×integer→integer, where add(x,y)=x+y\text{add}(x,y) = x + yadd(x,y)=x+y. Find add(7,9)\text{add}(7,9)add(7,9).
- Treat the input as one ordered pair:
(7, 9) belongs to integer×integer\text{integer} \times \text{integer}integer×integer.
- Substitute the pair values into the rule: add(7,9)=7+9\text{add}(7,9) = 7 + 9add(7,9)=7+9.
- Evaluate the result: 7+9=167 + 9 = 167+9=16, so the output is an integer, as required by the co-domain.
Partial function application
Partial function application means applying a function to fewer arguments than it ultimately needs, producing a new function that expects the remaining argument or arguments.
This idea relies on functions being first-class objects, because the result of partial application is itself a function.
A one-argument function has type:
f:A→Bf: A \rightarrow Bf:A→B
If you apply its single argument, the result has type BBB. There are no remaining arguments, so there is no useful partial application left to do.
A two-argument function can be viewed like this:
add:integer→(integer→integer)\text{add}: \text{integer} \rightarrow (\text{integer} \rightarrow \text{integer})add:integer→(integer→integer)
This means add takes one integer and returns a function. That returned function takes another integer and returns an integer.
The brackets may be dropped:
add:integer→integer→integer\text{add}: \text{integer} \rightarrow \text{integer} \rightarrow \text{integer}add:integer→integer→integer
So add 4\text{add}\ 4add 4 returns a new function that adds 4 to whatever integer it is later given.
A three-argument function can be viewed as:
h:A→B→C→Dh: A \rightarrow B \rightarrow C \rightarrow Dh:A→B→C→D
This means:
h:A→(B→(C→D))h: A \rightarrow (B \rightarrow (C \rightarrow D))h:A→(B→(C→D))
So:
- applying the first argument gives a function of type B→C→DB \rightarrow C \rightarrow DB→C→D;
- applying the first two arguments gives a function of type C→DC \rightarrow DC→D;
- applying all three arguments gives a final value of type DDD.
Arrow notation is right-associative
Read A→B→CA \rightarrow B \rightarrow CA→B→C as A→(B→C)A \rightarrow (B \rightarrow C)A→(B→C), not as (A→B)→C(A \rightarrow B) \rightarrow C(A→B)→C.
Partially applying a three-argument function
Let scaleAdd:integer→integer→integer→integer\text{scaleAdd}: \text{integer} \rightarrow \text{integer} \rightarrow \text{integer} \rightarrow \text{integer}scaleAdd:integer→integer→integer→integer, with scaleAdd(a,b,x)=a⋅x+b\text{scaleAdd}(a,b,x) = a \cdot x + bscaleAdd(a,b,x)=a⋅x+b. Work out what function is produced by scaleAdd 2 3\text{scaleAdd}\ 2\ 3scaleAdd 2 3.
- Apply the first argument, 2, to fix a=2a = 2a=2. The result is a function waiting for bbb and xxx.
- Apply the second argument, 3, to fix b=3b = 3b=3. The result is now a function waiting for only xxx.
- Substitute the fixed values into the rule: a⋅x+ba \cdot x + ba⋅x+b becomes 2⋅x+32 \cdot x + 32⋅x+3.
- Therefore, scaleAdd 2 3\text{scaleAdd}\ 2\ 3scaleAdd 2 3 is the function x↦2⋅x+3x \mapsto 2 \cdot x + 3x↦2⋅x+3.
Forgetting that partial application returns a function
add 4\text{add}\ 4add 4 is not the final numerical answer. It is a new function waiting for another integer.
Composition of functions
Function composition combines two functions to produce a new function.
Given:
f:A→Bf: A \rightarrow Bf:A→B
and:
g:B→Cg: B \rightarrow Cg:B→C
the composition g∘fg \circ fg∘f has type:
g∘f:A→Cg \circ f: A \rightarrow Cg∘f:A→C
This is read as “ggg composed with fff”. The important order is: apply fff first, then apply ggg to the result.
In function notation:
(g∘f)(x)=g(f(x))(g \circ f)(x) = g(f(x))(g∘f)(x)=g(f(x))
Composing two functions
Let f(x)=x+2f(x) = x + 2f(x)=x+2 and g(y)=y3g(y) = y^3g(y)=y3. Find (g∘f)(x)(g \circ f)(x)(g∘f)(x) and then evaluate it when x=3x = 3x=3.
- Apply fff first: f(x)=x+2f(x) = x + 2f(x)=x+2.
- Use the result of fff as the input to ggg: g(f(x))=g(x+2)g(f(x)) = g(x + 2)g(f(x))=g(x+2).
- Substitute into the rule for ggg: g(x+2)=(x+2)3g(x + 2) = (x + 2)^3g(x+2)=(x+2)3.
- Evaluate for x=3x = 3x=3: (3+2)3=53=125(3 + 2)^3 = 5^3 = 125(3+2)3=53=125.
Reversing the order of composition
g∘fg \circ fg∘f means apply fff first, then ggg. It does not mean apply ggg first.
Compatibility of types
For g∘fg \circ fg∘f to work, the output type of fff must match the input type of ggg. If f:A→Bf: A \rightarrow Bf:A→B and g:B→Cg: B \rightarrow Cg:B→C, then g∘f:A→Cg \circ f: A \rightarrow Cg∘f:A→C.
In the exam
- When you see f:A→Bf: A \rightarrow Bf:A→B, identify AAA as the domain and BBB as the co-domain.
- For partial application, state the type of the function that is returned after each argument is supplied.
- For composition, write (g∘f)(x)=g(f(x))(g \circ f)(x) = g(f(x))(g∘f)(x)=g(f(x)) to avoid reversing the order.
Check yourself
- What is the difference between a function’s domain and its co-domain?
- Why does partial function application require functions to be first-class objects?
- If f:A→Bf: A \rightarrow Bf:A→B and g:B→Cg: B \rightarrow Cg:B→C, what is the type of g∘fg \circ fg∘f?