A-level Computing/AQA/Paper 2/Fundamentals of functional programming/Basics of functional programming





A function is a rule that connects a set of inputs to given outputs. We can model the inputs as, with the outputs being chosen from the. It is not necessary that every member of  will be mapped to an input from. In the example below,  describes the inputs as being the Natural numbers (positive integers and zero, $${N}$$), the function is the doubling of the inputs. The outputs are from, the set of Natural numbers, note that not all elements of   are mapped from  , e.g. no doubling of a positive integer will ever map to the number 3.



Another name for the set that describes the inputs is the domain, the set from which the possible outputs are chosen is called the co-domain. The type of the domain and the co-domain do not have to be the same. For example we could have a function that told us whether a given positive integer input was a prime number. In this case the domain would be Natural numbers ($${N}$$), and the co-domain the boolean values True and False, as shown below:



Another way of explaining the working of functions is by describing the function type. The rule of the doubling function above can be written as, this describes function   being a rule that maps the argument (input) type   to result (output) type. Replacing  and   with their datatypes and   with a name gives us:

We can also write the  function as a function type:

Other examples of function types include:

First-class objects
In a functional programming language functions are first-class objects. This means that they can be used in the following ways:


 * be assigned to a variable
 * be assigned as arguments
 * be returned in function calls
 * appear in expressions

Let's see this in action (you will learn more about what this code codes as you follow this chapter),

You will have already used first-class objects when writing procedural programming code where integers, characters and other datatypes, along with variables are used as arguments, returned by function calls, appear in expressions and can be assigned to variables.

Haskell declarations
In Haskell when you want to declare a value and attach it to a name you can use the  command like most other languages:

If we wanted to declare our own version of pi, we could write:

But, as you hopefully remember, variables in functional programming are immutable, and we shouldn't be able to edit the value of  once we have declared it in a program:

Attempting to compile this code from the command line gives an error, Haskell won't let you declare the same thing twice. In other words it won't let you change the value of something once it has been declared, variables in Haskell are immutable:

This chapter gives a very simple introduction to Haskell declarations that resembles the construction of a variable or constant in other languages. The  and   commands offer better functionality, learn more about them over at learn you a haskell.

Writing our own functions
Now that we have learnt how to write simple functional programs using Haskell's inbuilt functions we will start to define our own functions. To do this we write the name of the function along with any arguments it might take, then set the return value as a calculation or short piece of code. For example:

$$\underbrace{byThePowerOf}_\text{function name} \underbrace{x \ y}_\text{arguments} = \underbrace{x ^\wedge y}_\text{calculations for output} $$

Haskell uses static typing, the type of every parameter and return value is known at compile time, unlike languages such as Python which are dynamically typed. When we write functions we can declare the types that should be used for the arguments and the output, meaning that we will have better control over how the compiler creates the functions we define.

There are several base types in Haskell (which are always written starting with a capital letter) including: ,,  ,  ,

Let us create a function that tells us if a number is magic or not, where three is the magic number. Before we write the code of the function, we define the name of the function, along with the type of the input  and the type of the output. For this we will be writing the code in a separate text file.

This means that when we load this code it will only accept integer inputs, anything else will return an error. And we also know that it will return a boolean value if given an integer input.

Other Haskell examples of declaring the function type and the function code include:

The output type is always the last datatype specified in in the  list. All the other datatypes define the inputs. In the  example above there are three types listed. The first two  data types specify the argument types and the last data type listed, the final , specifies the output type.

You can find out the type(s) of something in Haskell by using the  command. For example:

is odd as it is a type that doesn't start with capital letter like the other date type names, it is a type variable. This means that the  function isn't bound to using any particular type, but by it having   three times it means that we have to pass the same variable type to both arguments of the   function, and the   function will return a value of the same type as the arguments.

Find out more over at learn you a haskell

Function application
Giving inputs as arguments to a function is called the function application. is the application of the function del (delete) to the arguments 7 and 9. This can be written as:

Which describes the function  being defined by the cartesian product of two integers,  ; meaning any combination of both integer arguments can be accepted (x doesn't equal multiply). The final arrow (->) shows that the output of the function  on these integers is also an integer.

Whilst it looks like  accepts two arguments, because the argument is defined as a cartesian product,   only takes one argument, a pair of values, for example (7,9) or (101, 99).

Partial function application
Haskell might appear to have functions that take multiple arguments, e.g., but in reality a function in Haskell can only ever take one argument. How can this be? Looking at the example of the  function we can write the same function call in two different ways, both work:

The second example,  is showing a partial function application. As you know through mathematics and previous programming, the inner brackets are always executed first. This means the  runs with only one input, when it needs two?! The code within the brackets return a function that is still waiting for the missing input before it can return a value, this is why we call it a partial function,  only partially runs. To make this clearer let's declare  as a variable:

Whilst the above example is rather trivial, you can see that instead of having to write  multiple times, and all the mistypes that might entail, we can use the partial function   (Less Than L) instead.

We can describe the  function that we used above as the function type:

Passing a single Integer to  returned a function that took another Integer as an argument and returned an Integer. This can be written, with the brackets defining the return function, as:

Let's look at a more complex example that is trying to work out the volume of boxes. There are three Integer arguments  and one Integer output.

This can also be written as:

Let’s see how a partial function of boxVol can be used. By passing two arguments, 4 and 5, to  at the same time we first create a partial function with 4 as the argument x, and   as the expected arguments and output. Haskell then passes 5 to this partial function, forming a new partial function. This is declared as. has x = 4 and y = 5 and it accepts  as the expected argument and output. Passing 9 to the partial function  then completes the function which can now return the value 180 (4 * 5 * 9).



We create partial functions that have calculations involving one of more arguments already built into them. These partial functions are then ready to accept the other arguments to complete the function or make further partial functions. Partial functions can be used as the building blocks of other functions.

Function composition
Sometimes you might want to combine two functions together, this is called function composition. Let's imagine that we have a function  of function type   and another function , of function type. We can use function composition to make a new function through the command :

For function composition to work, the co-domain of  must match the domain of , e.g.   . Allowing the output of   to be mapped to the input of. We can see this by looking at this example:

We know that the domain of  matches the codomain of , and through   we take the input of   to be the output of

Another way of writing  is , which tells us that we should first calculate  , then map the output of   to the input of.

We can perform function composition in Haskell by using the full stop symbol '.'. Taking the above example, we can turn this into code:

To double check this is doing what we expect:
 * 1) If  ,
 * 2) then  ,
 * 3) mapping the output of   to the input of   through   gives  ,
 * 4) calculating   gives.
 * 5) Which is what we see above.


 * it allows us to build other functions out of pre-made blocks, or partial functions
 * it makes mistyping of common statements less likely


 * 251.32742
 * 301.5929


 * 1)   NO - domain of f is Integer, co-domain of g is Float
 * 2)   YES - domain of g in Integer, co-domain of h is Integer
 * 3)   NO - domain of h is Integer, co-domain of f is Bool
 * 4)   YES - domain of h is Integer, co-domain of h is Integer
 * 5)   NO - domain of g is Integer, co-domain of g is Float
 * 6)   NO - domain of g is Integer, co-domain of i is Bool


 * 0
 * 144
 * 316