Functional programming is based on the simplest of models, namely that of finding the value of an expression. This we meet in our first years at school, when we learn to work out expressions like 8+(3-2) by evaluating the two halves, 8 and (3-2), and adding the results together. Functional programming consists of our defining for ourselves functions like + which we can then use to form expressions.
We define these functions by means of equations, like
addD a b = 2*(a+b) (1)
which we use to calculate the value of an expression like addD 2 (addD 3 4). We evaluate this using (1) to replace occurrences of addD with their values, so that we can write down a calculation of its value
addD 2 (addD 3 4) = 2*(2 + (addD 3 4)) = 2*(2 + 2*(3 + 4)) = 32
As well as using (1) to calculate, we can read it as a logical description of how the function addD behaves on any values a and b; on the basis of this we can reason about how it behaves. For instance, for any values a and b,
addD a b = 2*(a+b) = 2*(b+a) = addD b a
This equation holds for all possible input values, in contrast to the information we gain from testing a function at a selection of inputs.
On top of this simple model we can build a variety of facilities, which give the functional approach its distinctive flavour. These include higher-order functions, whose arguments and results are themselves functions; polymorphism, which allows a single definition to apply simultaneously to a collection of types; and infinite data structures which are used to model a variety of data objects.
The Miranda language also has support for larger-scale programming, including user-defined algebraic types, such as lists, trees and so on; abstract data types and modules. These contribute to separating complex tasks into smaller sub-tasks, making the components of systems independent of each other, as well as supporting software re-use.
Next Up