Computer Science Canada

Beginners Guide to Haskell

Author:  haskell [ Sun Feb 11, 2007 11:34 am ]
Post subject:  Beginners Guide to Haskell

Excerpts from http://www.haskell.org/haskellwiki/Introduction
Quote:
Haskell is a computer programming language. In particular, it is a polymorphicly 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 lambda calculus, hence the lambda we use as a logo.


Quote:
1 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 Wink by my Haskell programming experience.

Graham Klyne


Haskell offers you:

o 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).
o Shorter, clearer, and more maintainable code.
o Fewer errors, higher reliability.
o A smaller "semantic gap" between the programmer and the language.
o 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.


Quote:
1.2 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.

Quicksort in Haskell

code:
qsort []     = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)


Quicksort in C

code:
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);

    t = a[l];
    a[l] = a[hi];
    a[hi] = t;

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



Quote:


Quote:


Quote:
1.2.3 1. Brevity

Functional programs tend to be much more concise than their imperative counterparts. Quicksort is a rather extreme case, but in general functional programs are much shorter (by a factor of two to ten).

1.2.4 2. Ease of understanding

Functional programs are often easier to understand. 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:

code:
qsort []     = []
qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)


The first line reads: "When you sort an empty list ([]), the result is another empty list". The second line reads: "To sort a list whose first element is named x and the rest of which is named xs, sort the elements of xs that are less than x, sort the elements of xs that are greater than or equal to x, and concatenate (++) the results, with x sandwiched in the middle."

1.2.5 3. 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.

1.2.6 4. 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.

1.2.7 5. 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

code:
grep printf Foo.c | wc


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

code:
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,

code:
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.

1.2.8 6. 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.

1.2.9 7. 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.


Quote:
1.3 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.

1.3.1 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.

1.4 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. First-time users may want to start with Hugs, a small, portable Haskell interpreter.

1.5 Does Anyone Use Functional Programming?

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

o 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.
o 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.
o 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 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 ... with encouraging results.
o A researcher at the MITRE corporation is using Haskell to prototype his digital signal-processing applications.
o 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.
o 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.
o 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.
o An incestuous example: the Glasgow Haskell compiler is written in Haskell: a 100,000-line application.
o Pugs, the leading perl6 implementation is written in Haskell
o As is Darcs, a cutting edge distributed revision control system

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.

1.6 Other frequently-asked questions

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 in 2nd place (behind C) in the Great Language Shootout, with other functional languages also ranked highly.

I already have a large application in C or C++; 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.

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:

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

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

Based on a paper by Simon Peyton Jones.
Recent content is available under a simple permissive license.


So now you know what Haskell is, and what it offers. I assume that you are interested.

Learning Haskell

The above link gives you all the resources you could possibly need to learn Haskell. As a compiler/interpreter package, I recommend the Glascow Haskell Compiler[GHC]. Available from the above link.

Now, you may be wondering your options for a code editor for Haskell. I recommend Haskell Mode for Emacs.

If you are an Eclipse person, try Haskell Support in Eclipse

If all else fails, you can try:

Haskell mode for Vim
Haskell Syntax Highlighting for Nedit

I hope you find this information useful in your quest for Haskell mastery!

Author:  rdrake [ Sun Feb 11, 2007 11:16 pm ]
Post subject:  RE:Beginners Guide to Haskell

Yet Another Haskell Tutorial.

Author:  haskell [ Mon Feb 12, 2007 12:18 pm ]
Post subject:  RE:Beginners Guide to Haskell

Correction.

Yet Another Haskell Tutorial powered by Google and sponsored by McDonalds. I'm loving it!


: