Difference between revisions of "Introduction"

From HaskellWiki
Jump to navigation Jump to search
(Broken links)
(→‎Aren't functional programs very slow?: Updated link and remark about relative speed)
(90 intermediate revisions by 36 users not shown)
Line 1: Line 1:
  +
[[Category:Tutorials]] [[Category:Language]]
 
Haskell is a computer programming language. In particular, it is a
 
Haskell is a computer programming language. In particular, it is a
<i> polymorphicly typed, lazy, purely functional </i> language, quite
+
'' [[Polymorphism|polymorphically]] [[typing|statically typed]], [[Lazy evaluation|lazy]], [[functional programming|purely functional]] '' language,
different from most other programming languages.
+
quite different from most other programming languages.
 
The language is named for [[Haskell Brooks Curry]], whose work in mathematical logic serves as a foundation for
 
The language is named for [[Haskell Brooks Curry]], whose work in mathematical logic serves as a foundation for
 
functional languages.
 
functional languages.
Haskell is based on <i>lambda calculus</i>, hence the lambda we use as
+
Haskell is based on the ''[[lambda calculus]]'', hence the lambda we use as a logo.
a logo.
 
   
   
== Why Use Haskell? ==
+
==Why use Haskell?==
 
 
Writing large software systems that
 
Writing large software systems that
 
work is difficult and expensive. Maintaining those systems is even
 
work is difficult and expensive. Maintaining those systems is even
Line 34: Line 33:
   
 
Haskell offers you:
 
Haskell offers you:
<ul>
 
<li>Substantially increased programmer productivity (Ericsson measured
 
an improvement factor of between 9 and 25 in one set of experiments on
 
telephony software).
 
<li>Shorter, clearer, and more maintainable code.
 
<li>Fewer errors, higher reliability.
 
<li>A smaller &quot;semantic gap&quot; between the programmer and the
 
language.
 
   
  +
*Substantially increased programmer productivity (Ericsson measured an improvement factor of between 9 and 25 using Erlang, a functional programming language similar to Haskell, in one set of experiments on telephony software).
<li>Shorter lead times.
 
  +
*Shorter, clearer, and more maintainable code.
</ul>
 
  +
*Fewer errors, higher reliability.
  +
*A smaller &quot;semantic gap&quot; between the programmer and the language.
  +
*Shorter lead times.
  +
 
Haskell is a wide-spectrum language, suitable for a variety of
 
Haskell is a wide-spectrum language, suitable for a variety of
 
applications. It is particularly suitable for programs which need to
 
applications. It is particularly suitable for programs which need to
 
be highly modifiable and maintainable.
 
be highly modifiable and maintainable.
   
Much of a software product's life is spent in <I>specification</I>,
+
Much of a software product's life is spent in ''specification'',
<I>design</I> and <I>maintenance</I>, and not in <I>programming</I>.
+
''design'' and ''maintenance'', and not in ''programming''.
 
Functional languages are superb for writing specifications which can
 
Functional languages are superb for writing specifications which can
 
actually be executed (and hence tested and debugged). Such a
 
actually be executed (and hence tested and debugged). Such a
specification then <I>is</I> the first prototype of the final
+
specification then ''is'' the first prototype of the final
 
program.
 
program.
   
 
Functional programs are also relatively easy to maintain, because the
 
Functional programs are also relatively easy to maintain, because the
 
code is shorter, clearer, and the rigorous control of side effects
 
code is shorter, clearer, and the rigorous control of side effects
eliminates a huge class of unforseen interactions.
+
eliminates a huge class of unforeseen interactions.
   
=== What is functional programming? ===
+
==What is functional programming?==
  +
C, Java, Pascal, Ada, and so on, are all ''imperative''
 
C, Java, Pascal, Ada, and so on, are all <I>imperative</I>
 
 
languages. They are &quot;imperative&quot; in the sense that they
 
languages. They are &quot;imperative&quot; in the sense that they
 
consist of a sequence of commands, which are executed strictly one
 
consist of a sequence of commands, which are executed strictly one
after the other. Haskell is a <i>functional</i> language. A
+
after the other. Haskell is a ''functional'' language. A
 
functional program is a single expression, which is executed by
 
functional program is a single expression, which is executed by
 
evaluating the expression.
 
evaluating the expression.
Line 71: Line 65:
 
Anyone who has used a spreadsheet has experience of functional
 
Anyone who has used a spreadsheet has experience of functional
 
programming. In a spreadsheet, one specifies the value of each cell
 
programming. In a spreadsheet, one specifies the value of each cell
in terms of the values of other cells. The focus is on <I>what</I> is
+
in terms of the values of other cells. The focus is on ''what'' is
to be computed, not <I>how</I> it should be computed. For
+
to be computed, not ''how'' it should be computed. For
 
example:
 
example:
  +
*we do not specify the order in which the cells should be calculated -&nbsp;instead we take it for granted that the spreadsheet will compute cells in an order which respects their dependencies.
 
  +
*we do not tell the spreadsheet how to allocate its memory - rather, we expect it to present us with an apparently infinite plane of cells, and to allocate memory only to those cells which are actually in use.
<ul>
 
  +
*for the most part, we specify the value of a cell by an ''expression'' (whose parts can be evaluated in any order), rather than by a ''sequence of commands '' which computes its value.
<li>we do not specify the order in which the cells should be
 
calculated -&nbsp;instead we take it for granted that the
 
spreadsheet will compute cells in an order which respects their
 
dependencies.
 
<li>we do not tell the spreadsheet how to allocate its memory
 
-&nbsp;rather, we expect it to present us with an apparently
 
infinite plane of cells, and to allocate memory only to those cells
 
which are actually in use.
 
<li>for the most part, we specify the value of a cell by an
 
<I>expression</I> (whose parts can be evaluated in any order), rather
 
by a <I>sequence of commands </I> which computes its
 
value.
 
</ul>
 
   
 
An interesting consequence of the spreadsheet's unspecified order
 
An interesting consequence of the spreadsheet's unspecified order
Line 108: Line 90:
 
relation should be computed, without saying how it should be computed.
 
relation should be computed, without saying how it should be computed.
 
Indeed, the query can be evaluated in any convenient order. SQL
 
Indeed, the query can be evaluated in any convenient order. SQL
implementations often perform extensive query optimisation which
+
implementations often perform extensive query optimization which
 
(among other things) figures out the best order in which to evaluate
 
(among other things) figures out the best order in which to evaluate
 
the expression.
 
the expression.
   
=== What's good about functional programming? ===
+
==What's good about functional programming?==
   
Spreadsheets and SQL are both fairly specialised languages.
+
Spreadsheets and SQL are both fairly specialized languages. Functional
Functional programming languages take the same ideas, and move them
+
programming languages take the same ideas and move them into the realm
into the realm of general-purpose programming. To get an idea of what
+
of general-purpose programming. To get an idea of what a functional
a functional program is like, look at the following quicksort programs.
+
program is like, and the expressiveness of functional languages, look at
They both sort a sequence of numbers into ascending order using a standard
+
the following quicksort programs. They both sort a sequence of numbers
method called "quicksort". The first program is written in Haskell
+
into ascending order using a standard method called "quicksort". The
and the second in C.
+
first program is written in Haskell and the second in C.
   
  +
Whereas the C program describes the particular steps the machine must
==== Quicksort in Haskell ====
 
  +
make to perform a sort -- with most code dealing with the low-level
  +
details of data manipulation -- the Haskell program encodes the sorting
  +
algorithm at a much higher level, with improved brevity and clarity as
  +
a result (at the cost of efficiency unless compiled by a very smart compiler):
   
  +
===Quicksort in Haskell===
<pre>
 
  +
qsort [] = []
 
  +
The first thing to know about Haskell's syntax is that parentheses are used for grouping, and not for function application. The application of a function <hask>f</hask> to an argument <hask>x</hask> is written <hask>f x</hask>, not necessarily <hask>f(x)</hask>. It can be written as <hask>(f x)</hask> to separate it from its surroundings.
qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x
 
  +
where
 
  +
<haskell>
elts_lt_x = [y | y &lt;- xs, y &lt; x]
 
  +
quicksort :: Ord a => [a] -> [a]
elts_greq_x = [y | y &lt;- xs, y &gt;= x]
 
  +
quicksort [] = []
</pre>
 
  +
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
  +
where
  +
lesser = filter (< p) xs
  +
greater = filter (>= p) xs
  +
  +
</haskell>
  +
The parentheses indicate the grouping of operands on the right-hand side of equations. On the left they indicate ''patterns'' of a function's argument(s). The parentheses around the two function calls <code>(quicksort lesser)</code> and <code>(quicksort greater)</code> are not necessary &ndash; because function application binds tighter than infix operators &ndash; and are there just for clarity.
  +
  +
Here <code>[]</code> stands for empty list, <code>[p]</code> for a singleton list holding one element <code>p</code>, <code>++</code> is a built-in list concatenation operator, and the two <code>filter</code> calls use two on-the-fly built predicates, first for getting all the elements of <code>xs</code> that are smaller than the pivot element <code>p</code>, and the other - all those greater than, or equal to it.
  +
  +
This definition uses Haskell's ability to define functions as equations with pattern-matching clauses: here the first one, with <code>[]</code> pattern for an empty list on its left-hand side, and the second, with <code>(p:xs)</code> pattern on its left-hand side standing for non-empty list with the head element <code>p</code> (used as a pivot element), and the tail <code>xs</code> (which is read, by convention, as ''axes'', suggesting that it is a list of several ''xs'', viz. elements ''"x"'').
  +
  +
The very first line above is the function's ''type signature'': it says that <code>quicksort</code> transforms a list of elements of some type <code>a</code> (usually read "alpha") into a list of the same type, for a type <code>a</code> that is an instance of typeclass <hask>Ord</hask> (which means that comparison operations are defined for it, so elements of type <code>a</code> can be compared with one another).
  +
  +
===Quicksort in C===
   
  +
True quicksort in C sorts in-place:
==== Quicksort in C ====
 
 
<pre>
 
<pre>
  +
// To sort array a[] of size n: qsort(a,0,n-1)
qsort( a, lo, hi ) int a[], hi, lo;
 
  +
  +
void qsort(int a[], int lo, int hi)
 
{
 
{
 
int h, l, p, t;
 
int h, l, p, t;
Line 155: Line 158:
 
} while (l &lt; h);
 
} while (l &lt; h);
   
t = a[l];
+
a[hi] = a[l];
a[l] = a[hi];
+
a[l] = p;
a[hi] = t;
 
   
 
qsort( a, lo, l-1 );
 
qsort( a, lo, l-1 );
Line 163: Line 165:
 
}
 
}
 
}
 
}
 
 
</pre>
 
</pre>
  +
Let's examine some of benefits of Haskell and functional programming.
 
  +
A [[/Direct Translation | semi-direct translation]] of the C code is here.
  +
  +
Let's examine some of the benefits of Haskell and functional programming.
 
A more detailed case for functional programming can be found in
 
A more detailed case for functional programming can be found in
  +
 
<BLOCKQUOTE>
 
<BLOCKQUOTE>
[http://www.md.chalmers.se/~rjmh/Papers/whyfp.html <STRONG>Why Functional Programming Matters</STRONG>] by [http://www.md.chalmers.se/~rjmh/ John Hughes], The Computer
+
[http://www.cse.chalmers.se/~rjmh/Papers/whyfp.pdf '''Why Functional Programming Matters'''] by [http://www.cse.chalmers.se/~rjmh/ John Hughes], The Computer
 
Journal, Vol. 32, No. 2, 1989, pp. 98 - 107. Also in: David A. Turner
 
Journal, Vol. 32, No. 2, 1989, pp. 98 - 107. Also in: David A. Turner
 
(ed.): Research Topics in Functional Programming, Addison-Wesley,
 
(ed.): Research Topics in Functional Programming, Addison-Wesley,
Line 175: Line 180:
 
A slightly less formal essay inspired by the paper above can be found in
 
A slightly less formal essay inspired by the paper above can be found in
 
<BLOCKQUOTE>
 
<BLOCKQUOTE>
[[Why Haskell Matters |<STRONG>Why Haskell Matters</STRONG>]] originally by [mailto:sylvan@dtek.chalmers.se Sebastian Sylvan]
+
[[Why Haskell matters |'''Why Haskell Matters''']] originally by [mailto:sylvan@dtek.chalmers.se Sebastian Sylvan]
 
</BLOCKQUOTE>
 
</BLOCKQUOTE>
   
==== 1. Brevity ====
+
===Ease of understanding===
  +
Functional programs are often easier to '''understand''': it is usually possible to get their meaning at a glance. The same certainly cannot be said of the C program. It takes quite a while to understand, and even when you do understand it, it is extremely easy to make a small slip and end up with an incorrect program.
Functional programs tend to be much more <B>concise</B> than their
 
imperative counterparts. Quicksort is a rather extreme case, but in
 
general functional programs are much shorter (two to ten times).
 
==== 2. Ease of understanding ====
 
Functional programs are often easier to <B>understand</B>.
 
You should be able to understand the program without any previous
 
knowledge of
 
either Haskell or quicksort. The same certainly cannot be said of
 
the C program. It takes quite a while to understand, and even when
 
you do understand it, it is extremely easy to make a small slip and
 
end up with an incorrect program. Here is a detailed explanation of
 
the Haskell quicksort:
 
<blockquote>
 
<pre>
 
qsort [] = []
 
qsort (x:xs) = qsort elts_lt_x ++ [x] ++ qsort elts_greq_x
 
where
 
elts_lt_x = [y | y &lt;- xs, y &lt; x]
 
elts_greq_x = [y | y &lt;- xs, y &gt;= x]
 
   
  +
Here is a detailed explanation of the Haskell quicksort:
</pre>
 
The first line reads:
 
"The result of sorting an empty list (written <tt>[]</tt>) is an empty list".
 
The second line reads: "To sort a list whose first element is <tt>x</tt> and
 
the rest of which is called <tt>xs</tt>, just sort all the elements of
 
<tt>xs</tt> which are less than <tt>x</tt> (call them
 
<tt>elts_lt_x</tt>), sort all the elements of <tt>xs</tt>
 
   
  +
<haskell>
which are greater than or equal to <tt>x</tt> (call them
 
  +
quicksort [] = []
<tt>elts_greq_x</tt>), and
 
  +
</haskell>
concatenate (<tt>++</tt>) the results, with <tt>x</tt> sandwiched in
 
  +
The first clause reads: "The result of sorting an empty list (<tt>[]</tt>) is just an empty list (<tt>[]</tt>)".
the middle."
 
   
  +
<haskell>
The definition of <tt>elts_lt_x</tt>, which is given immediately
 
  +
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
below, is read like this: "<tt>elts_lt_x</tt> is the list of all
 
  +
where
  +
lesser = filter (< p) xs
  +
greater = filter (>= p) xs
  +
</haskell>
  +
The second clause reads: "The result of sorting a non-empty list whose first element will be henceforth referred to as <tt>p</tt> and
  +
the rest of which will be referred to as <tt>xs</tt>, is a result of concatenating three sublists: first the result of sorting the elements of <tt>xs</tt> that are less than <tt>p</tt>, then <tt>p</tt> itself, and then the result of sorting the elements of <tt>xs</tt> that are greater than or equal to <tt>p</tt>."
   
  +
===Brevity===
<tt>y</tt>'s such that <tt>y</tt> is drawn from
 
  +
Functional programs tend to be much more '''concise''', shorter by a factor of two to ten usually, than their imperative counterparts.
the list <tt>xs</tt>, and <tt>y</tt> is less than <tt>x</tt>". The
 
definition of <tt>elts_greq_x</tt> is similar.
 
The syntax is deliberately reminiscent of standard mathematical set
 
notation, pronouncing "<tt>|</tt>" as "such that" and "<tt>
 
   
  +
The above could be written even more concisely with the help of [[list comprehension]]s:
&lt;-</tt>" as "drawn from".
 
  +
<haskell>
  +
qsort (p:xs) = qsort [x | x<-xs, x<p] ++ [p] ++ qsort [x | x<-xs, x>=p]
  +
</haskell>
   
  +
The first sub-expression means, for <code>x</code> drawn from <code>xs</code> in order, such that <code>x < p</code>, collect <code>x</code>s in a list and call the <code>qsort</code> function with it, recursively. Similarly for the last one.
When asked to sort a non-empty list, <tt>qsort</tt> calls itself to sort
 
<tt>elts_lt_x</tt> and <tt>elts_greq_x</tt>. That's OK because both these lists are
 
smaller than the one originally given to <tt>qsort</tt>, so the
 
splitting-and-sorting process will eventually reduce to sorting an
 
empty list, which is done rather trivially by the first line of <tt>qsort</tt>.
 
</blockquote>
 
   
==== 3. No core dumps ====
+
===No core dumps===
Most functional languages, and Haskell in particular, are <B>strongly
+
Most functional languages, and Haskell in particular, are '''strongly
typed</B>, eliminating a huge class of easy-to-make errors at compile
+
typed''', eliminating a huge class of easy-to-make errors at compile
time. In particular, strong typing means <B>no core dumps</B>!
+
time. In particular, strong typing means '''no core dumps'''!
 
There is simply no possibility of treating an integer as a pointer, or
 
There is simply no possibility of treating an integer as a pointer, or
 
following a null pointer.
 
following a null pointer.
   
==== 4. Code re-use ====
+
===Code re-use===
Of course, strong typing is available in many imperative languages,
+
Of course, strong typing is available in many imperative languages, such as Ada or Pascal. However, Haskell's type system is much less restrictive than, say, Pascal's, because it uses '''[[polymorphism]]'''.
  +
such as Ada or Pascal. However, Haskell's type system is much less
 
  +
For example, the qsort program given in Figure 1 will not only sort lists of integers, but also lists of floating point numbers, lists of characters, lists of lists; indeed, it will sort lists of ''anything'' for which it is meaningful to have "less-than" and "greater-than" operations. In contrast, the C version can only sort an array of integers, and nothing else.
restrictive than, say, Pascal's, because it uses <B>polymorphism</B>.
 
For example, the qsort program given in Figure 1 will not only sort
 
lists of integers, but also lists of floating point numbers, lists of
 
characters, lists of lists; indeed, it will sort lists of anything
 
which can be compared by the less-than and greater-than operations.
 
In contrast, the C version is restricted to sorting an array of
 
integers.
 
   
 
Polymorphism enhances re-usability.
 
Polymorphism enhances re-usability.
   
==== 5. Strong glue ====
+
===Strong glue===
Non-strict functional languages have another powerful feature: they
+
"Non-strict" functional languages, such as Haskell, have another powerful feature: they
 
only evaluate as much of the program as is required to get the answer
 
only evaluate as much of the program as is required to get the answer
- this is called <B>lazy evaluation</B>. This feature is rather
+
- this is called [[Haskell/Lazy evaluation |'''lazy evaluation''']]. This feature is rather
 
like Unix pipes. For example, the Unix command
 
like Unix pipes. For example, the Unix command
 
<pre>
 
<pre>
 
grep printf Foo.c | wc
 
grep printf Foo.c | wc
 
</pre>
 
</pre>
counts the number of lines in the file <tt> Foo.c </tt>which include the
+
counts the number of lines in the file <tt> Foo.c </tt>that include the
string <tt>printf</tt>
+
string <tt>printf</tt>.
The command &quot;<tt>grep printf Foo.c</tt>&quot;
+
The command
  +
<pre>
 
  +
grep printf Foo.c
  +
</pre>
 
produces all lines which contain the string &quot;<tt>printf</tt>&quot;,
 
produces all lines which contain the string &quot;<tt>printf</tt>&quot;,
 
while the &quot;<tt>wc</tt>&quot; command counts them. The pipe,
 
while the &quot;<tt>wc</tt>&quot; command counts them. The pipe,
Line 269: Line 247:
 
the second. In this way, no large intermediate files need be
 
the second. In this way, no large intermediate files need be
 
produced. You can think of <tt>wc</tt> &quot;demanding&quot;
 
produced. You can think of <tt>wc</tt> &quot;demanding&quot;
lines from the <tt>grep</tt>
+
lines from the <tt>grep</tt>.
   
 
If the second command only needs some of the output of the first, then
 
If the second command only needs some of the output of the first, then
 
execution of the first command might never need to be completed. For
 
execution of the first command might never need to be completed. For
example
+
example,
   
 
<pre>
 
<pre>
Line 282: Line 260:
 
the fact that its execution might be abandoned.
 
the fact that its execution might be abandoned.
   
Non-strict languages provide exactly this kind of demand-driven
+
[[Lazy vs. non-strict |Non-strict]] languages provide exactly this kind of demand-driven
 
evaluation. Data structures are evaluated just enough to deliver the
 
evaluation. Data structures are evaluated just enough to deliver the
 
answer, and parts of them may not be evaluated at all. As in the case
 
answer, and parts of them may not be evaluated at all. As in the case
 
of Unix commands, this provides powerful &quot;glue&quot; with which
 
of Unix commands, this provides powerful &quot;glue&quot; with which
 
to compose existing programs together. What this means is that it is
 
to compose existing programs together. What this means is that it is
possible to <B>re-use programs</B>, or pieces of programs, much more
+
possible to '''re-use programs''', or pieces of programs, much more
often than can be done in an imperative setting. Lazy evaluation
+
often than can be done in an imperative setting. [[Haskell/Lazy evaluation |Lazy evaluation]] allows us to write more '''[[modular programs]]'''.
allows us to write more <B>modular programs</b>.
 
   
==== 6. Powerful abstractions ====
+
===Powerful abstractions===
 
In general, functional languages offer powerful new ways to
 
In general, functional languages offer powerful new ways to
encapsulate <B>abstractions</B>. An abstraction allows you to define
+
encapsulate '''abstractions'''. An abstraction allows you to define
 
an object whose internal workings are hidden; a C procedure, for
 
an object whose internal workings are hidden; a C procedure, for
example, is an abstraction. Abstractions are <I>the</I> key to
+
example, is an abstraction. Abstractions are ''the'' key to
 
building modular, maintainable programs, so much so that a good
 
building modular, maintainable programs, so much so that a good
 
question to ask of any new language is "what mechanisms for
 
question to ask of any new language is "what mechanisms for
Line 301: Line 278:
   
 
One powerful abstraction mechanism available in functional languages
 
One powerful abstraction mechanism available in functional languages
is the <B>higher-order function</B>. In Haskell a function is a
+
is the '''[[higher order function]]'''. In Haskell a function is a
 
first-class citizen: it can freely be passed to other functions,
 
first-class citizen: it can freely be passed to other functions,
 
returned as the result of a function, stored in a data structure, and
 
returned as the result of a function, stored in a data structure, and
so on. It turns out that the judicious use of higher-order functions
+
so on. It turns out that the judicious use of higher order functions
 
can substantially improve the structure and modularity of many
 
can substantially improve the structure and modularity of many
 
programs.
 
programs.
   
<h4> 7. Built-in memory management</h4>
+
===Built-in memory management===
  +
Very many sophisticated programs need to allocate dynamic memory from a heap. In C this is done with a call to <tt> malloc</tt>, followed by code to initialize the store just allocated. The programmer is responsible for returning the store to the free pool when it isn't needed any more, a notorious source of "dangling-pointer" errors. To make matters worse, <tt>malloc</tt> is fairly expensive performance-wise, so programmers often <tt>malloc</tt> a single large chunk of store, and then allocate "by hand" out of this.
Very many sophisticated programs need to allocate dynamic memory from
 
a heap. In C this is done with a call to <tt> malloc</tt>, followed by code to
 
initialise the store just allocated. The programmer is responsible
 
for returning the store to the free pool when it isn't needed any
 
more, a notorious source of &quot;dangling-pointer&quot; errors.
 
Furthermore, <tt>malloc</tt> is fairly expensive, so programmers often
 
   
  +
Every functional language relieves the programmer of this storage management burden. Store is allocated and initialized implicitly, and recovered automatically by the garbage collector. The technology of storage allocation and garbage collection is now well developed, and the performance costs are rather slight.
<tt>malloc</tt> a single large chunk
 
of store, and then allocate &quot;by hand&quot; out of this.
 
   
  +
==When C is better==
Every functional language relieves the programmer of this storage
 
management burden. Store is allocated and initialised implicitly, and
 
recovered automatically by the garbage collector. The technology of
 
storage allocation and garbage collection is now well developed, and
 
the costs are rather slight.
 
 
<h3>When C is better</h3>
 
 
It isn't all roses, of course. The C quicksort uses an extremely
 
It isn't all roses, of course. The C quicksort uses an extremely
 
ingenious technique, invented by Hoare, whereby it sorts the array
 
ingenious technique, invented by Hoare, whereby it sorts the array
<I>in place</I>; that is, without using any extra storage. As a
+
''in place''; that is, without using any extra storage. As a
 
result, it runs quickly, and in a small amount of memory. In
 
result, it runs quickly, and in a small amount of memory. In
 
contrast, the Haskell program allocates quite a lot of extra memory
 
contrast, the Haskell program allocates quite a lot of extra memory
Line 337: Line 302:
 
run-time storage management costs.
 
run-time storage management costs.
   
In applications where performance is required at any cost, or when the
+
In applications where [[performance]] is required at any cost, or when the
 
goal is detailed tuning of a low-level algorithm, an imperative
 
goal is detailed tuning of a low-level algorithm, an imperative
 
language like C would probably be a better choice than Haskell,
 
language like C would probably be a better choice than Haskell,
 
exactly because it provides more intimate control over the exact way
 
exactly because it provides more intimate control over the exact way
in which the computation is carried out.
+
in which the computation is carried out - that is, until sufficiently smart compiler appears that is able to derive the C equivalent from the Haskell one-liner, all by itself.
 
==== Functional vs imperative ====
 
   
  +
===Functional vs imperative===
 
But few programs require performance at any cost! After all, we all
 
But few programs require performance at any cost! After all, we all
 
stopped writing assembly-language programs, except perhaps for key
 
stopped writing assembly-language programs, except perhaps for key
Line 362: Line 326:
 
For most programs the result is perfectly acceptable.
 
For most programs the result is perfectly acceptable.
   
<h3>What is Haskell?</h3>
+
==What is Haskell?==
 
Haskell is a modern, standard, non-strict, purely-functional
 
Haskell is a modern, standard, non-strict, purely-functional
 
programming language. It provides all the features sketched above,
 
programming language. It provides all the features sketched above,
Line 375: Line 339:
 
more conventional integer, floating-point and boolean types.
 
more conventional integer, floating-point and boolean types.
   
There are a number of [[Compilers and interpreters|compilers and interpreters]] available. All are
+
There are a number of [[implementations|compilers and interpreters]] available. All are
  +
free. The recommend way to install Haskell on your computer is through the the [http://hackage.haskell.org/platform/ Haskell Platform].
free. First-time users may want to start with [[Hugs]], a small, portable Haskell interpreter.
 
   
  +
See also the [[History of Haskell]].
=== Does Anyone Use Functional Programming? ===
 
   
  +
==Does anyone use functional programming?==
 
Functional programming languages are used in substantial applications.
 
Functional programming languages are used in substantial applications.
 
For example:
 
For example:
  +
* Software AG, a major German software company, market an expert system (Natural Expert) which is programmed in a functional language. Their users find it easy to develop their applications in this language, through which they gain access to an underlying database system. It all runs on an IBM mainframe.
<ul>
 
  +
*Ericsson have developed a new functional language, Erlang, to use in their future telephony applications. They have already written 130k-line Erlang applications, and find them very much shorter and faster to develop.
<li>
 
  +
*Amoco ran an experiment in which they re-coded in Miranda, a lazy functional language, a substantial fraction of their main oil-reservoir simulation code, a critical application. The resulting program was vastly shorter, and its production revealed a number of errors in the existing software. Amoco subsequently transcribed the functional program into C++ with encouraging results.
Software AG, a major German software company, market an expert system
 
  +
*A researcher at the MITRE corporation is using Haskell to prototype his digital signal-processing applications.
(Natural Expert) which is programmed in a functional language. Their
 
  +
*Researchers at Durham University used Miranda, and later Haskell, in a seven-year project to build LOLITA, a 30,000-line program for natural-language understanding.
users find it easy to develop their applications in this language,
 
  +
*Query is the query language of the O2 object-oriented database system. O2Query is probably the most sophisticated commercially-available object-oriented database query language and it is a functional language.
through which they gain access to an underlying database system. It
 
  +
*ICAD Inc market a CAD system for mechanical and aeronautical engineers. The language in which the engineers describe their design is functional, and it uses lazy evaluation extensively to avoid recomputing parts of the design which are not currently visible on the screen. This results in substantial performance improvements.
all runs on an IBM mainframe.
 
  +
*An incestuous example: the Glasgow Haskell compiler is written in Haskell: a 100,000-line application.
<li>Ericsson have developed a new functional language, Erlang, to use
 
  +
*[http://pugscode.org Pugs], which was the leading perl6 implementation, is written in Haskell
in their future telephony applications. They have already written
 
  +
*As is [http://darcs.net Darcs], a cutting edge distributed revision control system
130k-line Erlang applications, and find them very much shorter and
 
faster to develop.
 
<li>Amoco ran an experiment in which they re-coded in a functional
 
language a substantial fraction of their main oil-reservoir simulation
 
code, a critical applictaion. The resulting program was vastly
 
shorter, and its production revealed a number of errors in the
 
existing software. Amoco subsequently transcribed the functional
 
program into ... with encouraging results.
 
<li>A researcher at the MITRE corporation is using Haskell to
 
prototype his digital signal-processing applications.
 
<li>Researchers at Durham University used a functional language in a
 
seven-year project to build LOLITA, a 30,000-line program for
 
natural-language understanding.
 
<li>Query is the query language of the O2 object-oriented database
 
system. O2Query is probably the most sophisticated
 
commercially-available object-oriented database query language
 
and it is a functional language.
 
<li>ICAD Inc market a CAD system for mechanical and aeronautical
 
engineers. The language in which the engineers describe their design
 
is functional, and it uses lazy evaluation extensively to avoid
 
recomputing parts of the design which are not currently visible on the
 
screen. This results in substantial performance improvements.
 
<li>An incestuous example: the Glasgow Haskell compiler is written in
 
Haskell: a 30,000-line application.
 
</ul>
 
Some other examples of [[Haskell in practice]] are found at this web site.
 
   
  +
Some other examples of [[Haskell in practice]].
=== Other frequently-asked questions ===
 
   
  +
Clifford Beshers, of [http://www.linspire.com/ Linspire Inc]., describes their experience with Haskell, and functional programming:
<i>Is functional programming hard to learn?</i>
 
  +
  +
<blockquote>
  +
Linspire, Inc. has used functional programming since its inception in
  +
2001, beginning with extensive use of O'Caml, with a steady shift to
  +
Haskell as its implementations and libraries have matured. Hardware
  +
detection, software packaging and CGI web page generation are all areas
  +
where we have used functional programming extensively.
  +
</blockquote>
  +
  +
<blockquote>
  +
Haskell's feature set lets us replace much of our use of little
  +
languages (e.g., bash or awk) and two-level languages (C or C++ bound to
  +
an interpreted language), allowing for faster development, better code
  +
sharing and ultimately faster implementations. Above all, we value
  +
static type checking for minimizing runtime errors in applications that
  +
run in unknown environments and for wrapping legacy programs in strongly
  +
typed functions to ensure that we pass valid arguments.
  +
</blockquote>
  +
  +
==Other frequently-asked questions==
  +
  +
There is also a [[FAQ|larger FAQ]] in progress.
  +
  +
===''Is functional programming hard to learn?''===
 
<blockquote>
 
<blockquote>
 
Functional programming does require a change in perspective, which
 
Functional programming does require a change in perspective, which
Line 428: Line 392:
 
that they can "pick it up on the day".
 
that they can "pick it up on the day".
 
</blockquote>
 
</blockquote>
<I>Aren't functional programs very slow?</i>
+
===''Aren't functional programs very slow?''===
 
<blockquote>They used to be, perhaps 20 years ago. But the compilers
 
<blockquote>They used to be, perhaps 20 years ago. But the compilers
 
have long since caught up. Haskell programs run fast for all but the
 
have long since caught up. Haskell programs run fast for all but the
 
most performance-demanding applications. At the time of writing, Haskell
 
most performance-demanding applications. At the time of writing, Haskell
compiled via GHC is in 2nd place (behind C) in the
+
compiled via GHC is doing quite well in the
  +
[https://benchmarksgame-team.pages.debian.net/benchmarksgame/ The Computer Language Benchmarks Game], with other functional languages also ranked highly.
[http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=all Great Language Shootout],
 
with other functional languages also ranked highly.
 
 
</blockquote>
 
</blockquote>
   
<i>I already have a large application in C or C++; can I benefit from
+
===''I already have a large application in C or C++.''===
functional programming without rewriting my whole system?</i>
+
Also worded as: ''Can I benefit from functional programming without rewriting my whole system?''
 
<blockquote>
 
<blockquote>
   
Line 447: Line 410:
 
programs to work with software components. Low level C/C++ interfaces
 
programs to work with software components. Low level C/C++ interfaces
 
can be generated with
 
can be generated with
[http://www.haskell.org/greencard Green Card], allowing
+
[http://hackage.haskell.org/package/greencard Green Card] or
  +
[http://www.cse.unsw.edu.au/~chak/haskell/c2hs/ C->Haskell], allowing
 
tight integration between Haskell and C. These tools have been used
 
tight integration between Haskell and C. These tools have been used
to build a number of successful, mixed language systems.
+
to build a large number of successful, mixed language systems.
 
</blockquote>
 
</blockquote>
   
<i> What libraries does Haskell support?</i>
+
==='' What libraries does Haskell support?''===
 
<blockquote>
 
<blockquote>
 
Many software libraries have been developed for Haskell. See the
 
Many software libraries have been developed for Haskell. See the
Line 460: Line 424:
 
</blockquote>
 
</blockquote>
   
<i> What other software tools for Haskell are there? </i>
+
==='' What other software tools for Haskell are there? ''===
 
<blockquote>
 
<blockquote>
 
Glasgow Haskell comes with a profiler which allows you to find which
 
Glasgow Haskell comes with a profiler which allows you to find which
Line 466: Line 430:
 
Haskell has a space-profiling tool, and a quasi-parallel simulator
 
Haskell has a space-profiling tool, and a quasi-parallel simulator
 
which allows you to experiment with running your program in
 
which allows you to experiment with running your program in
parallel. Hugs also has some similar tools.
+
parallel. Hugs also has some similar tools. For a complete list, check
  +
the [[Libraries and tools|tools page]].
 
</blockquote>
 
</blockquote>
   
  +
===''How can I ask for help?''===
<I>Can I get a support contract or a help-line?</i>
 
  +
There is a large community of Haskell users willing to help. They can be contacted on mailing lists, IRC, or Stack Overflow.
  +
  +
===''Can I get a support contract or a help-line?''===
 
<blockquote>
 
<blockquote>
 
It used to be the case that if you wanted help, you had to persuade a
 
It used to be the case that if you wanted help, you had to persuade a
Line 478: Line 446:
 
[[Consultants|directory of Haskell Consultants]] who provide:
 
[[Consultants|directory of Haskell Consultants]] who provide:
   
  +
*Support for compilers, tools and libraries.
<ul>
 
  +
*Help with improving code quality (time, space, robustness, maintainability, etc.) using code reviews and tools.
<LI>Support for compilers, tools and libraries.</LI>
 
  +
*Help with using libraries, tools and advanced Haskell features such as type system extensions, exception handling, the foreign function interface, test harnesses, and concurrency.
<LI>Help with improving code quality (time, space, robustness,
 
  +
*Library and application development.
maintainability, etc.) using code reviews and tools.</LI>
 
  +
*Staff training.
<LI>
 
Help with using libraries, tools and advanced Haskell features such as
 
type system extensions, exception handling, the foreign
 
function interface, test harnesses, and concurrency.
 
</LI>
 
   
<LI>Library and application development.</LI>
 
 
<LI>Staff training.</li>
 
</ul>
 
 
These companies and individuals tend to work closely with those
 
These companies and individuals tend to work closely with those
 
developing Haskell (indeed, they have usually made major
 
developing Haskell (indeed, they have usually made major
Line 497: Line 457:
   
 
</blockquote>
 
</blockquote>
<i>How can I learn Haskell?</i>
+
===''How can I learn Haskell?''===
  +
<blockquote>
  +
The easiest way to learn Haskell is with a [[Books|textbook]]. There are a lot of [[Tutorials|online tutorials]], but you'll have a much easier time to learn the basics from a book. After all, Haskell is very different from traditional mainstream languages, it's like learning programming anew.
  +
</blockquote>
  +
  +
===''Comparisons to other languages''===
 
<blockquote>
 
<blockquote>
  +
[[Comparison of functional programming languages | Click to see a table comparing features of Haskell to similar languages]]
For more example and explanations, look at the [http://www.haskell.org/tutorial/ Gentle Introduction to Haskell]. There are a
 
number of textbooks that use Haskell; see [[Books]].
 
 
</blockquote>
 
</blockquote>
   
<i>Based on a paper by Simon Peyton Jones.</i>
+
''Based on a paper by Simon Peyton Jones.''

Revision as of 23:47, 26 August 2018

Haskell is a computer programming language. In particular, it is a polymorphically statically typed, lazy, purely functional language, quite different from most other programming languages. The language is named for Haskell Brooks Curry, whose work in mathematical logic serves as a foundation for functional languages. Haskell is based on the lambda calculus, hence the lambda we use as a logo.


Why use Haskell?

Writing large software systems that work is difficult and expensive. Maintaining those systems is even more difficult and expensive. Functional programming languages, such as Haskell, can make it easier and cheaper. For example, a new user who wrote a small relational DBMS in Haskell had this to say:

WOW! I basically wrote this without testing just thinking about my program in terms of transformations between types. I wrote the test/example code and had almost no implementation errors in the code! The compiler/type-system is really really good at preventing you from making coding mistakes! I've never in my life had a block of code this big work on the first try. I am WAY impressed.

Even if you are not in a position to use Haskell in your programming projects, learning Haskell can make you a better programmer in any language.

I learned Haskell a couple of years ago, having previously programmed in Python and (many) other languages. Recently, I've been using Python for a project (the choice being determined by both technical and non-technical issues), and find my Python programming style is now heavily influenced (for the better, I hope ;-) by my Haskell programming experience.

Graham Klyne


Haskell offers you:

  • Substantially increased programmer productivity (Ericsson measured an improvement factor of between 9 and 25 using Erlang, a functional programming language similar to Haskell, in one set of experiments on telephony software).
  • Shorter, clearer, and more maintainable code.
  • Fewer errors, higher reliability.
  • A smaller "semantic gap" between the programmer and the language.
  • Shorter lead times.

Haskell is a wide-spectrum language, suitable for a variety of applications. It is particularly suitable for programs which need to be highly modifiable and maintainable.

Much of a software product's life is spent in specification, design and maintenance, and not in programming. Functional languages are superb for writing specifications which can actually be executed (and hence tested and debugged). Such a specification then is the first prototype of the final program.

Functional programs are also relatively easy to maintain, because the code is shorter, clearer, and the rigorous control of side effects eliminates a huge class of unforeseen interactions.

What is functional programming?

C, Java, Pascal, Ada, and so on, are all imperative languages. They are "imperative" in the sense that they consist of a sequence of commands, which are executed strictly one after the other. Haskell is a functional language. A functional program is a single expression, which is executed by evaluating the expression.

Anyone who has used a spreadsheet has experience of functional programming. In a spreadsheet, one specifies the value of each cell in terms of the values of other cells. The focus is on what is to be computed, not how it should be computed. For example:

  • we do not specify the order in which the cells should be calculated - instead we take it for granted that the spreadsheet will compute cells in an order which respects their dependencies.
  • we do not tell the spreadsheet how to allocate its memory - rather, we expect it to present us with an apparently infinite plane of cells, and to allocate memory only to those cells which are actually in use.
  • for the most part, we specify the value of a cell by an expression (whose parts can be evaluated in any order), rather than by a sequence of commands which computes its value.

An interesting consequence of the spreadsheet's unspecified order of re-calculation is that the notion of assignment is not very useful. After all, if you don't know exactly when an assignment will happen, you can't make much use of it! This contrasts strongly with programs in conventional languages like C, which consist essentially of a carefully-specified sequence of assignments, or Java, in which the ordering of method calls is crucial to the meaning of a program.

This focus on the high-level "what" rather than the low-level "how" is a distinguishing characteristic of functional programming languages.

Another well-known nearly-functional language is the standard database query language SQL. An SQL query is an expression involving projections, selections, joins and so forth. The query says what relation should be computed, without saying how it should be computed. Indeed, the query can be evaluated in any convenient order. SQL implementations often perform extensive query optimization which (among other things) figures out the best order in which to evaluate the expression.

What's good about functional programming?

Spreadsheets and SQL are both fairly specialized languages. Functional programming languages take the same ideas and move them into the realm of general-purpose programming. To get an idea of what a functional program is like, and the expressiveness of functional languages, look at the following quicksort programs. They both sort a sequence of numbers into ascending order using a standard method called "quicksort". The first program is written in Haskell and the second in C.

Whereas the C program describes the particular steps the machine must make to perform a sort -- with most code dealing with the low-level details of data manipulation -- the Haskell program encodes the sorting algorithm at a much higher level, with improved brevity and clarity as a result (at the cost of efficiency unless compiled by a very smart compiler):

Quicksort in Haskell

The first thing to know about Haskell's syntax is that parentheses are used for grouping, and not for function application. The application of a function f to an argument x is written f x, not necessarily f(x). It can be written as (f x) to separate it from its surroundings.

quicksort :: Ord a => [a] -> [a]
quicksort []     = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) xs

The parentheses indicate the grouping of operands on the right-hand side of equations. On the left they indicate patterns of a function's argument(s). The parentheses around the two function calls (quicksort lesser) and (quicksort greater) are not necessary – because function application binds tighter than infix operators – and are there just for clarity.

Here [] stands for empty list, [p] for a singleton list holding one element p, ++ is a built-in list concatenation operator, and the two filter calls use two on-the-fly built predicates, first for getting all the elements of xs that are smaller than the pivot element p, and the other - all those greater than, or equal to it.

This definition uses Haskell's ability to define functions as equations with pattern-matching clauses: here the first one, with [] pattern for an empty list on its left-hand side, and the second, with (p:xs) pattern on its left-hand side standing for non-empty list with the head element p (used as a pivot element), and the tail xs (which is read, by convention, as axes, suggesting that it is a list of several xs, viz. elements "x").

The very first line above is the function's type signature: it says that quicksort transforms a list of elements of some type a (usually read "alpha") into a list of the same type, for a type a that is an instance of typeclass Ord (which means that comparison operations are defined for it, so elements of type a can be compared with one another).

Quicksort in C

True quicksort in C sorts in-place:

// To sort array a[] of size n: qsort(a,0,n-1)

void qsort(int a[], int lo, int hi) 
{
  int h, l, p, t;

  if (lo < hi) {
    l = lo;
    h = hi;
    p = a[hi];

    do {
      while ((l < h) && (a[l] <= p)) 
          l = l+1;
      while ((h > l) && (a[h] >= p))
          h = h-1;
      if (l < h) {
          t = a[l];
          a[l] = a[h];
          a[h] = t;
      }
    } while (l < h);

    a[hi] = a[l];
    a[l] = p;

    qsort( a, lo, l-1 );
    qsort( a, l+1, hi );
  }
}

A semi-direct translation of the C code is here.

Let's examine some of the benefits of Haskell and functional programming. A more detailed case for functional programming can be found in

Why Functional Programming Matters by John Hughes, The Computer Journal, Vol. 32, No. 2, 1989, pp. 98 - 107. Also in: David A. Turner (ed.): Research Topics in Functional Programming, Addison-Wesley, 1990, pp. 17 - 42.

A slightly less formal essay inspired by the paper above can be found in

Why Haskell Matters originally by Sebastian Sylvan

Ease of understanding

Functional programs are often easier to understand: it is usually possible to get their meaning at a glance. The same certainly cannot be said of the C program. It takes quite a while to understand, and even when you do understand it, it is extremely easy to make a small slip and end up with an incorrect program.

Here is a detailed explanation of the Haskell quicksort:

quicksort []     = []

The first clause reads: "The result of sorting an empty list ([]) is just an empty list ([])".

quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) xs

The second clause reads: "The result of sorting a non-empty list whose first element will be henceforth referred to as p and the rest of which will be referred to as xs, is a result of concatenating three sublists: first the result of sorting the elements of xs that are less than p, then p itself, and then the result of sorting the elements of xs that are greater than or equal to p."

Brevity

Functional programs tend to be much more concise, shorter by a factor of two to ten usually, than their imperative counterparts.

The above could be written even more concisely with the help of list comprehensions:

qsort (p:xs) = qsort [x | x<-xs, x<p] ++ [p] ++ qsort [x | x<-xs, x>=p]

The first sub-expression means, for x drawn from xs in order, such that x < p, collect xs in a list and call the qsort function with it, recursively. Similarly for the last one.

No core dumps

Most functional languages, and Haskell in particular, are strongly typed, eliminating a huge class of easy-to-make errors at compile time. In particular, strong typing means no core dumps! There is simply no possibility of treating an integer as a pointer, or following a null pointer.

Code re-use

Of course, strong typing is available in many imperative languages, such as Ada or Pascal. However, Haskell's type system is much less restrictive than, say, Pascal's, because it uses polymorphism.

For example, the qsort program given in Figure 1 will not only sort lists of integers, but also lists of floating point numbers, lists of characters, lists of lists; indeed, it will sort lists of anything for which it is meaningful to have "less-than" and "greater-than" operations. In contrast, the C version can only sort an array of integers, and nothing else.

Polymorphism enhances re-usability.

Strong glue

"Non-strict" functional languages, such as Haskell, have another powerful feature: they only evaluate as much of the program as is required to get the answer - this is called lazy evaluation. This feature is rather like Unix pipes. For example, the Unix command

grep printf Foo.c | wc

counts the number of lines in the file Foo.c that include the string printf. The command

grep printf Foo.c

produces all lines which contain the string "printf", while the "wc" command counts them. The pipe, written "|", takes the output from the first command and delivers it to the second. The two commands execute together, so that the output of the first is consumed more-or-less immediately by the second. In this way, no large intermediate files need be produced. You can think of wc "demanding" lines from the grep.

If the second command only needs some of the output of the first, then execution of the first command might never need to be completed. For example,

grep printf Foo.c | head 5

just prints the first 5 lines which contain "printf". There is no need to modify the grep command to take account of the fact that its execution might be abandoned.

Non-strict languages provide exactly this kind of demand-driven evaluation. Data structures are evaluated just enough to deliver the answer, and parts of them may not be evaluated at all. As in the case of Unix commands, this provides powerful "glue" with which to compose existing programs together. What this means is that it is possible to re-use programs, or pieces of programs, much more often than can be done in an imperative setting. Lazy evaluation allows us to write more modular programs.

Powerful abstractions

In general, functional languages offer powerful new ways to encapsulate abstractions. An abstraction allows you to define an object whose internal workings are hidden; a C procedure, for example, is an abstraction. Abstractions are the key to building modular, maintainable programs, so much so that a good question to ask of any new language is "what mechanisms for abstraction does it provide?".

One powerful abstraction mechanism available in functional languages is the higher order function. In Haskell a function is a first-class citizen: it can freely be passed to other functions, returned as the result of a function, stored in a data structure, and so on. It turns out that the judicious use of higher order functions can substantially improve the structure and modularity of many programs.

Built-in memory management

Very many sophisticated programs need to allocate dynamic memory from a heap. In C this is done with a call to malloc, followed by code to initialize the store just allocated. The programmer is responsible for returning the store to the free pool when it isn't needed any more, a notorious source of "dangling-pointer" errors. To make matters worse, malloc is fairly expensive performance-wise, so programmers often malloc a single large chunk of store, and then allocate "by hand" out of this.

Every functional language relieves the programmer of this storage management burden. Store is allocated and initialized implicitly, and recovered automatically by the garbage collector. The technology of storage allocation and garbage collection is now well developed, and the performance costs are rather slight.

When C is better

It isn't all roses, of course. The C quicksort uses an extremely ingenious technique, invented by Hoare, whereby it sorts the array in place; that is, without using any extra storage. As a result, it runs quickly, and in a small amount of memory. In contrast, the Haskell program allocates quite a lot of extra memory behind the scenes, and runs rather slower than the C program.

In effect, the C quicksort does some very ingenious storage management, trading this algorithmic complexity for a reduction in run-time storage management costs.

In applications where performance is required at any cost, or when the goal is detailed tuning of a low-level algorithm, an imperative language like C would probably be a better choice than Haskell, exactly because it provides more intimate control over the exact way in which the computation is carried out - that is, until sufficiently smart compiler appears that is able to derive the C equivalent from the Haskell one-liner, all by itself.

Functional vs imperative

But few programs require performance at any cost! After all, we all stopped writing assembly-language programs, except perhaps for key inner loops, long ago. The benefits of having a more supportive programming model (an arbitrary number of named, local variables instead of a fixed number of registers, for example) far outweigh the modest run-time costs.

Similarly, we willingly accept the costs of a virtual memory paging system, in exchange for the more supportive programming model of an infinite virtual address space. The days of explicit memory overlays are over.

Functional languages take another large step towards a higher-level programing model. Programs are easier to design, write and maintain, but the language offers the programmer less control over the machine. For most programs the result is perfectly acceptable.

What is Haskell?

Haskell is a modern, standard, non-strict, purely-functional programming language. It provides all the features sketched above, including polymorphic typing, lazy evaluation and higher-order functions. It also has an innovative type system which supports a systematic form of overloading and a module system.

It is specifically designed to handle a wide range of applications, from numerical through to symbolic. To this end, Haskell has an expressive syntax, and a rich variety of built-in data types, including arbitrary-precision integers and rationals, as well as the more conventional integer, floating-point and boolean types.

There are a number of compilers and interpreters available. All are free. The recommend way to install Haskell on your computer is through the the Haskell Platform.

See also the History of Haskell.

Does anyone use functional programming?

Functional programming languages are used in substantial applications. For example:

  • Software AG, a major German software company, market an expert system (Natural Expert) which is programmed in a functional language. Their users find it easy to develop their applications in this language, through which they gain access to an underlying database system. It all runs on an IBM mainframe.
  • Ericsson have developed a new functional language, Erlang, to use in their future telephony applications. They have already written 130k-line Erlang applications, and find them very much shorter and faster to develop.
  • Amoco ran an experiment in which they re-coded in Miranda, a lazy functional language, a substantial fraction of their main oil-reservoir simulation code, a critical application. The resulting program was vastly shorter, and its production revealed a number of errors in the existing software. Amoco subsequently transcribed the functional program into C++ with encouraging results.
  • A researcher at the MITRE corporation is using Haskell to prototype his digital signal-processing applications.
  • Researchers at Durham University used Miranda, and later Haskell, in a seven-year project to build LOLITA, a 30,000-line program for natural-language understanding.
  • Query is the query language of the O2 object-oriented database system. O2Query is probably the most sophisticated commercially-available object-oriented database query language and it is a functional language.
  • ICAD Inc market a CAD system for mechanical and aeronautical engineers. The language in which the engineers describe their design is functional, and it uses lazy evaluation extensively to avoid recomputing parts of the design which are not currently visible on the screen. This results in substantial performance improvements.
  • An incestuous example: the Glasgow Haskell compiler is written in Haskell: a 100,000-line application.
  • Pugs, which was the leading perl6 implementation, is written in Haskell
  • As is Darcs, a cutting edge distributed revision control system

Some other examples of Haskell in practice.

Clifford Beshers, of Linspire Inc., describes their experience with Haskell, and functional programming:

Linspire, Inc. has used functional programming since its inception in 2001, beginning with extensive use of O'Caml, with a steady shift to Haskell as its implementations and libraries have matured. Hardware detection, software packaging and CGI web page generation are all areas where we have used functional programming extensively.

Haskell's feature set lets us replace much of our use of little languages (e.g., bash or awk) and two-level languages (C or C++ bound to an interpreted language), allowing for faster development, better code sharing and ultimately faster implementations. Above all, we value static type checking for minimizing runtime errors in applications that run in unknown environments and for wrapping legacy programs in strongly typed functions to ensure that we pass valid arguments.

Other frequently-asked questions

There is also a larger FAQ in progress.

Is functional programming hard to learn?

Functional programming does require a change in perspective, which some programmers find hard. But Ericsson's experience in training programmers in Erlang is that most find the transition easy - provided they take the training need seriously rather than assuming that they can "pick it up on the day".

Aren't functional programs very slow?

They used to be, perhaps 20 years ago. But the compilers

have long since caught up. Haskell programs run fast for all but the most performance-demanding applications. At the time of writing, Haskell compiled via GHC is doing quite well in the The Computer Language Benchmarks Game, with other functional languages also ranked highly.

I already have a large application in C or C++.

Also worded as: Can I benefit from functional programming without rewriting my whole system?

Haskell has been successfully integrated into existing applications in a number of ways. HaskellDirect is an IDL (Interface Description Language) based tool that allows Haskell programs to work with software components. Low level C/C++ interfaces can be generated with Green Card or C->Haskell, allowing tight integration between Haskell and C. These tools have been used to build a large number of successful, mixed language systems.

What libraries does Haskell support?

Many software libraries have been developed for Haskell. See the list of Haskell libraries for a list of much of what is available.

What other software tools for Haskell are there?

Glasgow Haskell comes with a profiler which allows you to find which parts of your program are consuming most time and space. Chalmers Haskell has a space-profiling tool, and a quasi-parallel simulator which allows you to experiment with running your program in parallel. Hugs also has some similar tools. For a complete list, check the tools page.

How can I ask for help?

There is a large community of Haskell users willing to help. They can be contacted on mailing lists, IRC, or Stack Overflow.

Can I get a support contract or a help-line?

It used to be the case that if you wanted help, you had to persuade a Haskell research group that your problem was interesting enough or important enough that they should spend time helping you for free.
Whilst that is still an option, there is now a directory of Haskell Consultants who provide:

  • Support for compilers, tools and libraries.
  • Help with improving code quality (time, space, robustness, maintainability, etc.) using code reviews and tools.
  • Help with using libraries, tools and advanced Haskell features such as type system extensions, exception handling, the foreign function interface, test harnesses, and concurrency.
  • Library and application development.
  • Staff training.

These companies and individuals tend to work closely with those developing Haskell (indeed, they have usually made major contributions to Haskell themselves).

How can I learn Haskell?

The easiest way to learn Haskell is with a textbook. There are a lot of online tutorials, but you'll have a much easier time to learn the basics from a book. After all, Haskell is very different from traditional mainstream languages, it's like learning programming anew.

Comparisons to other languages

Click to see a table comparing features of Haskell to similar languages

Based on a paper by Simon Peyton Jones.