Functional Programming
Function evaluation is the basic concept for a programming paradigm that has been implemented in such functional programming languages as ML.
The language ML (``Meta Language'') was originally introduced in the 1970's as part of a theorem proving system, and was intended for describing and implementing proof strategies. Standard ML of New Jersey (SML) is an implementation of ML.
The basic mode of computation in ML, as in other functional languages, is the use of the definition and application of functions.
The basic cycle of ML activity has three parts:
Here is a simple example (in SML):
- 3;
val it = 3 : int
The first line contains the SML prompt, followed by an expression typed in by the user and ended by a semicolon.
The second line is SML's response, indicating the value of the input expression and its type.
Interacting with SML
SML has a number of built-in operators and data types. For instance, it provides the standard arithmetic operators.
- 3+2;
val it = 5 : int
- sqrt(2.0);
val it = 1.41421356237309 : real
The Boolean values true and false are available, as are logical operators such as not (negation), andalso (conjunction), and orelse (disjunction).
- not(true);
val it = false : bool
- true andalso false;
val it = false : bool
SML is a strongly typed language in that all (well-formed) expressions have a type that can be determined by examining the expression.
As part of the evaluation process, SML determines the type of the output value.
Binding Names to Values
In SML one can associate identifiers with values,
- val three = 3;and thereby establish a new value binding,
val three = 3 : int
- three;More complex expressions can also be used to bind values to names,
val it = 3 : int
- val five = 3+2;Names can then be used in other expressions,
val five = 5 : int
- three + five;
val it = 8 : int
Defining Functions in SML
The general form of a function definition in SML is
funidentifier
(
parameters
) =
expression
;
For example,
- fun double(x) = 2*x;declares double as a function from integers to integers.
val double = fn : int -> int
- double(222);If we apply it to an argument of the wrong type, we get an error message:
val it = 444 : int
- double(2.0);
Error: operator and operand don't agree
The user may also explicitly specify types:
- fun max(x:int,y:int,z:int) =
= if ((x>y) andalso (x>z)) then x
= else (if (y>z) then y else z);
val max = fn : int * int * int -> int
- max(3,2,2);
val it = 3 : int
Recursive Definitions
The use of recursive definitions is a main characteristic of functional programming languages.
These languages strongly encourage the use of recursion as a structuring mechanism in preference to iterative constructs such as while-loops.
Example.
- fun factorial(x) = if x=0 then 1The definition is used by SML to evaluate applications of the function to specific arguments.
= else x*factorial(x-1);
val factorial = fn : int -> int
- factorial(5);
val it = 120 : int
- factorial(10);
val it = 3628800 : int
Lists
Another built-in data structure in SML are lists.
A list in SML is essentially a finite sequence of objects, all of the same type:
- [1,2,3];The last example is a list of lists of integers, in SML notation int list list.
val it = [1,2,3] : int list
- [true,false, true];
val it = [true,false,true] : bool list
- [[1,2,3],[4,5],[6]];
val it = [[1,2,3],[4,5],[6]] : int list list
All objects in a list must be of the same type:
- [1,[2]];
Error: operator and operand don't agree
The empty list is denoted by the following symbol:
- [];Note that the type is described in terms of a type variable 'a, as a list of objects of type 'a. Instantiating the type variable, by types such as int, results in (different) empty lists of corresponding types.
val it = [] : 'a list
Operations on Lists
SML provides some predefined functions for manipulating lists.
The function hd returns the first element of its argument list.
- hd[1,2,3];Applying this function to the empty list will result in an error.
val it = 1 : int
- hd[[1,2],[3]];
val it = [1,2] : int list
The function tl removes the first element of its argument lists, and returns the remaining list.
- tl[1,2,3];The application of this function to the empty list will also result in an error.
val it = [2,3] : int list
- tl[[1,2],[3]];
val it = [[3]] : int list list
The types of the two functions are as follows:
- hd;
val it = fn : 'a list -> 'a
- tl;
val it = fn : 'a list -> 'a list
More List Operations
Lists can be constructed by the (binary) function :: that adds its first argument to the front of the second argument.
- 5::[];Again, the arguments must be of the right type:
val it = [5] : int list
- 1::[2,3];
val it = [1,2,3] : int list
- [1,2]::[[3],[4,5,6,7]];
val it = [[1,2],[3],[4,5,6,7]] : int list list
- [1]::[2,3];
Error: operator and operand don't agree
List can also be compared for equality:
- [1,2,3]=[1,2,3];
val it = true : bool
- [1,2]=[2,1];
val it = false : bool
- tl[1] = [];
val it = true : bool
Defining List Functions
Recursion is particularly useful for defining list processing functions.
For example, consider the problem of defining an SML function, call it concat, that takes as arguments two lists of the same type and returns the concatenated list.
For example, the following applications of the function concat should yield the indicated responses.
- concat([1,2],[3]);In defining such list processing functions, it is helpful to keep in mind that a list is either
val it = [1,2,3] : int list
- concat([],[1,2]);
val it = [1,2] : int list
- concat([1,2],[]);
val it = [1,2] : int list
- [1,2,3]=1::[2,3];
val it = true : bool
Concatenation of Lists
In designing a function for concatenating two lists x and y we thus distinguish two cases, depending on the form of x:
This suggests the following recursive definition.
- fun concat(x,y) = if x=[] then y
= else hd(x)::concat(tl(x),y);
val concat = fn : ''a list * ''a list -> ''a list
This seems to work (at least on some examples):
- concat([1,2],[3,4,5]);
val it = [1,2,3,4,5] : int list
- concat([],[1,2]);
val it = [1,2] : int list
- concat([1,2],[]);
val it = [1,2] : int list
- concat([],[]);
val it = [] : ''a list