Introduction To Functional Programming: John Harrison University of Cambridge
Introduction To Functional Programming: John Harrison University of Cambridge
Introduction To Functional Programming: John Harrison University of Cambridge
Introduction to
Functional Programming
John Harrison
University of Cambridge
Lecture 1
Introduction and Overview
Topics covered:
Imperative programming
Functional programming
The merits of functional programming
Overview of the course
Lambda notation and its bene ts
Imperative programming
Imperative (or procedural) programs rely on
modifying a state by using a sequence of
commands.
The state is mainly modi ed by the assignment
command, written v = E or v := E.
We can execute one command before another by
writing them in sequence, perhaps separated by a
semicolon: C1 ; C2 .
Commands can be executed conditionally using
if, and repeatedly using while.
Programs are a series of instructions on how to
modify the state.
Imperative languages, e.g. FORTRAN, Algol, C,
Modula-3 support this style of programming.
An abstract view
We ignore input-output operations, and assume
that a program runs for a limited time, producing
a result.
We can consider the execution in an abstract way
as:
0 ! 1 ! 2 ! ! n
Functional programming
A functional program is simply an expression, and
executing the program means evaluating the
expression.
There is no state, i.e. there are no variables.
Therefore there is no assignment, since there's
nothing to assign to.
And there is no sequencing and no repetition,
since one expression does not a ect another.
But on the positive side:
We can have recursive functions, giving
something comparable to repetition.
Functions can be used much more exibly,
e.g. we can have higher order functions.
Functional languages support this style of
programming.
John Harrison University of Cambridge, 16 January 1997
Introduction to Functional Programming: Lecture 1 5
Why?
At rst sight a language without variables,
assignment and sequencing looks very impractical.
We will show in this course how a lot of
interesting programming can be done in the
functional style.
Imperative programming languages have arisen as
an abstraction of the hardware, from machine
code, through assemblers and macro assemblers,
to FORTRAN and beyond.
Perhaps this is the wrong approach and we should
approach the task from the human side. Maybe
functional languages are better suited to people.
But what concrete reasons are there for preferring
functional languages?
Denotational semantics
We can identify our ML factorial function with an
abstract mathematical (partial) function Z ! Z :
8
< n! if n 0
[ fact]](n) = :
? otherwise
Lambda notation
Lambda notation is a way of denoting functions,
invented by Alonzo Church in the 1930s. We
write:
x: E [x]
Why?
In informal mathematics, when talking about a
function, one normally gives it a name: `de ne
f (x) = E [x] . . . then f '.
Similarly, most programming languages will only
let you de ne functions if you are prepared to
give them a name.
This approach is rather inconsistent. It means we
are not treating functions on a par with other
mathematical objects. We don't say:
De ne x and y by x = 2 and y = 4
respectively. Then xx = y
Lambda notation helps to put functions on an
equal footing. This is important in functional
programming.
Bene ts of -notation
The -notation can be useful too in order to make
mathematics clearer.
When we discuss x + xy, we are often vague
about whether we mean the value for a particular
x, or a function of x (or y . . . ). Using -notation
this can be made explicit.
In fact, using just:
Variables, e.g. x, y.
Constants, e.g. 3, true, +.
Applications of functions to arguments, e.g.
f x.
Lambda abstractions of expressions over
variables, e.g. x: x + y
we reach a general `abstract syntax' for
mathematics.
John Harrison University of Cambridge, 16 January 1997
Introduction to Functional Programming: Lecture 1 16
Currying
We can have functions of more than one
argument by using, for example x: y: x + y.
We can think of this as a function Z ! (Z ! Z ).
When given one argument, say 2, it returns a
function Z ! Z that adds 2 to its argument, and
this takes the second argument. This device is
known as currying, after Haskell Curry.
We adopt the conventions that x y: E [x; y] means
x: y: E [x; y], and that function application
associates to the left, e.g. that f x y means
(f (x))(y). This supports the use of currying, e.g.
(x y: x + y) 1 2 = (y: 1 + y) 2 = 1 + 2
Variable binding
Many constructs in mathematics bind variables.
The variable x in
Za
3x2 dx
0
kn=0 n2
Example of di erentiation
For example, the everyday construct d x2 can be
dx
analyzed as follows:
D (x: EXP x 2) x
Russell's paradox
Originally, Church hoped to use -notation to
give a foundation for mathematics, by introducing
constants for logical operations, e.g. : to mean
`not'. Unfortunately this turned out to be
inconsistent, because de ning R = x: : (x x) we
have:
R R = (x: : (x x)) R = : (R R)
R = fx j x 62 xg