A computer's processor performs operations under the control of a program.
These operations are in the form of commands.
A typical command might be “take the integer number currently held in
register number 6, add it to the integer constant 1, and put the
result back in register number 6”.
On an ARM processor (the processor used in the majority of cellphones),
the command is represented as a pattern of 32 bits, which happens to
be <tt>E2866001</tt> when shown in heaxadecimal notation.
It would be unreasonable to expect programmers to write code in hexadecimal
like that. Instead, they use a more user-friendly programming language to code
the software and they invoke system tools to translate their programs into
the machine code of the computer.
The usual tool which performs this translation is a compiler,
which typically works in concert with a linker and a loader
to put the machine code into the computer's memory.
(Sometimes an interpreter may be used to achieve a similar effect.)
But what kind of style should a computer program have? Should it resemble
the machine code of the computer? We could, for example, use a programming
language which lets us write the line
<tt>counter = counter + 1;</tt>
The correspondence between this line of code and the example ARM instruction
given above should be evident.
Indeed, some of the older programming languages such as FORTRAN were
designed with statements deliberately similar in nature to the commands
which control the computer processor.
These languages have a style which is known as imperative because
programs can be read as sequences of commands which the computer must obey.
The Basic and C languages would be other examples of imperative languages.
However, there is no reason why a programming language should be designed
around the concept of a command.
The only requirements are that the notation provided by the programming language
must allow us to specify the software in a convenient manner and it must be
possible to build a compiler (or an interpreter) for executing the software
on a computer.
There are several alternatives to the imperative style for a programming
language. They include object-oriented programming,
logic programming, and functional programming.
The term programming paradigm
is often used to describe the style of a programming language.
Some programming languages closely adhere to a particular programming
paradigm: for example Smalltalk is almost purely object-oriented and
Haskell is almost purely functional.
Other languages, for pragmatic reasons, straddle two or more camps
and support features from more than one paradigm.
For example, Java and C++ provide features from both the object oriented
and the imperative paradigms.
C# is similar to Java but some features from the functional paradigm have
also been added to the newest versions of the language.
F# is a language where the functional paradigm dominates, but where
the imperative and the object-oriented paradigms also play strong roles.
So, what is this functional programming paradigm? The following sections
should provide a brief introduction to the main ideas.
The Basis of Functional Programming
Every (useful) computer program takes input in some form and produces output
in some form.
That input may be generated by keystrokes on the keyboard, from data bytes
in a disk file, by a stylus on a touch sensitive screen, or in many other
ways. However, when the input reaches the program, it has been converted
to bit patterns (and these are equivalent to numbers).
The program's output may take the form of characters or images drawn on
a screen, data bytes written to a file, sounds emitted by a speaker, or
many other forms again. However, the program itself generates only bit
patterns to produce all these different kinds of output.
In its simplest form, a computer program inputs numbers and produces
numbers as its result.
With this viewpoint, a program is very similar in nature to
a mathematical function.
For example, the line of mathematics
let h = sin(π/4)
could be viewed as a request to evaluate the sine function with
π/4 as its input and to use the name h
for the output, i.e. the function result.
A useful programming language needs more than the ability to
invoke predefined functions like the sine function.
It particularly needs the ability to define new functions.
Mathematics provides some notations for that too.
The notations can be recursive too.
For example, the familiar factorial function could be defined
In a typical functional programming language, that function
definition might be programmed like this:
let factorial n =
if n = 0 then 1
else factorial (n - 1) * n
(This definition is almost in, but not quite, F# notation.)
The main characteristics of a ‘pure’ functional programming
- the program consists of a sequence of function definitions,
- functions can contain local definitions of other functions (i.e. they can be nested),
- functions cannot have side-effects (e.g. if the name h has been associated
with some value, then invoking a function cannot cause h to suddenly
be associated with a different value).
These characteristics are consistent with mathematical conventions.
One of the earliest researchers who worked on the idea of using mathematical functions
to describe computations was Alonzo Church.
He developed a notation known as lambda calculus,
and that notation became the basis for the first functional programming language to go into widespread
use -- Lisp 1.5.
One of Church's contributions was to provide a notation for defining a function without giving
it a name (the so-called anonymous function).
Although it sounds trivial, the notation is so useful that it has been incorporated into major
languages such as Python and C# (as well as in all the functional languages in common use).
A second major contribution was to consider functions to be first-class values.
What that means in practice is that a function can be passed as an argument to another function,
and that it is also possible for a function to create a new function on the fly and return
that as a result.
Again, all the functional languages in common use do treat functions as being first-class values.
Functions which accept other functions as argument are known as higher-order functions.
Why Functional Programming Is Important
The original functional programming language, LISP 1.5,
was widely used for artificial intelligence (AI) applications because of its suitability for
The name LISP is short for “LISt Processing”, indicating that lists are
used as the main data structure in LISP programming.
Lisp and its descendant languages (which include Scheme and Common Lisp) are
still important in the AI community.
The functional programming paradigm has, however, many followers outside the AI community.
A functional programming language is taught as the first programming language at many
universities and colleges. Why do they do that?
And software written in functional languages is becoming ever important in industry.
Some of the answers to these questions are listed below.
Use as a Teaching Language
While many educators want to teach a programming language, such as C++ or Java, which
is immediately useful as a job skill, other educators have a different focus.
They want their students to first learn how to design an algorithm, how to reason
about their software, and above all to understand the concepts clearly.
An imperative programming language like C (or an object-oriented language with
imperative features like Java, C# or C++) presents many difficulties to beginners
because of unexpected side-effects in their code and difficulties dealing with
pointers or references. Too often, a beginner goes into a edit-run-debug cycle
that leads to an (apparently) working program without ever really understanding
what their code is doing.
A functional programming language forces the programmer to break up a
problem into smaller functions.
It forces the programmer to know what each function is supposed to do.
Each function can be individually tested.
There is an entire discipline of program development which is
sadly lacking in the imperative paradigm (and is too often
absent in the object-oriented paradigm).
It is the experience of the universities and colleges which teach
functional programming first that their students have no trouble
learning languages like C or Java afterwards.
On the other hand, students whose first language is C or Java
appear to have difficulty adapting to a functional language
and may never become comfortable with recursion.
Use in Industry
Many commercial applications have been developed in functional
A partial list appears in the Wikipedia
page on functional programming.
The reasons for choosing a functional language include:
- reliability (functional programs tend to contain fewer bugs),
- coding productivity (functional programs tend to be shorter than their
equivalents in other languages),
- efficiency on multiprocessor systems.
The last point needs some further elaboration.
In a typical programming language such as C/C++, C# or Java, a function or method
call of this form
result1 = M(Exp1, Exp2);
must have the argument expressions Exp1 and Exp2
evaluated one after the other.
This is because in languages with side-effects,
evaluation of the argument Exp1 may affect the value of Exp2.
However, in a functional language, the two expressions may be evaluated
concurrently because they are side-effect free.
On a multicore processor, that possibility exists.
Another benefit of a functional language is that if a second invocation
like this one
result2 = M(Exp1, Exp2);
is executed, the call to M can be suppressed because
the second call must yield the same result as the first one.
(The call to M is side-effect free.)
A good implementation of the language would cache the result of
the first call and save it for later use.
As the numbers of processor cores increase, a new approach to
programming is needed to take proper advantage of that potential for
increased processing power.
Functional programming languages are seen as being a possible answer.
F# as a Practical Functional Language
Although the functional paradigm is prominent in F#, there is
also strong support for the imperative paradigm (in the form
of mutable datatypes), and for the object-oriented paradigm
(in that classes can be defined and instantiated).
These extra features have been added for efficiency and for
interoperability with the .NET class library.
If a program is maintaining a large data structure, such as
an array, it is much more efficient to update an element of
that array in place than it is to make a new copy of the
array but with a different value for that one element.
Making a copy would be the pure functional approach to handling
Although an advocate for pure functional programming would
argue that an array is an inappropriate data structure (perhaps
one should use a list or a tree instead), an array is a
memory-efficient data structure which is widely used in software.
Providing arrays and allowing them to be mutable is a pragmatic
choice for F#.
The inclusion of classes and object-orientation in general in F#
is another pragmatic choice.
Classes support inheritance and those provide a flexible form
of software reuse, and that is already a strong reason to
support them in F#.
Another reason is that a major software library, the .NET framework,
is usable from within F# programs only if class instances (objects)
can be created and used.
Access to the .NET framework allows production quality software
with rich user interfaces to be developed entirely in F#.
The F# tutorial accessible through this Try F# website should
get you started with F# programming and help you discover
whether it is a language you would want to use.
We hope it is.