Haskell
Haskell is a standardized pure functional programming language with non-strict semantics named after the logician Haskell Curry. It was created by a committee formed in 1987 for the express purpose of defining such a language. The direct predecessor of Haskell was Miranda, devised in 1985. The latest official language standard outside the standardization organizations is Haskell 98, intended to specify a minimal, portable version of the language for teaching and as a base for future extensions.
The language continues to evolve rapidly, with Hugs and GHC (see below) representing the current de facto standard.
Characterizing syntax features in Haskell include pattern matching, currying, list comprehensions, guards, and definable operators. The language also supports recursive functions and algebraic data types, as well as lazy evaluation. Unique concepts include monads, and type classes. The combination of such features can make functions which would be difficult to write in a procedural programming language almost trivial to implement in Haskell.
The language is, as of 2002, the lazy functional language on which the most research is being performed. Several variants have been developed: parallelizable versions from MIT and Glasgow, both called Parallel Haskell; more parallel and distributed versions called Distributed Haskell (formerly Goffin) and Eden; a speculatively evaluating version called Eager Haskell and several object oriented versions: Haskell++, O'Haskell and Mondrian.
Although Haskell has a comparatively small user community, its strengths have been well applied to a few projects. Audrey Tang's Pugs is an implementation for the forthcoming Perl 6 language with an interpreter and compilers that proved useful already after just a few months of its writing. Darcs is a revision control system, with several innovative features.
There is also a Haskell-like language that offers a new method of support for GUI development called Concurrent Clean. Its biggest deviation from Haskell is in the use of uniqueness types for input as opposed to monads.
Examples
The "Hello World" of functional languages is the factorial function. Expressed as pure Haskell:
fac :: Integer -> Integer fac 0 = 1 fac n | n > 0 = n *fac (n-1)
Or on a single line:
let { fac 0 = 1; fac n | n > 0 = n *fac (n-1) }
This describes the factorial as a recursive function, with a single terminating base case. It is similar to the descriptions of factorials found in mathematics textbooks. Much of Haskell code is similar to mathematics in facility and syntax.
The first line of the factorial function shown is optional, and describes the types of this function. It can be read as the function fac (fac) has type (::) from integer to integer (Integer -> Integer). That is, it takes an integer as an argument, and returns another integer.
The second line relies on pattern matching, an important feature of Haskell. Note that parameters of a function are not in parentheses but separated by spaces. When the function's argument is 0 (zero) it will return the integer 1 (one). For all other cases the third line is tried. This is the recursion, and executes the function again until the base case is reached.
A guard protects the third line from negative numbers for which a factorial is undefined. Without the guard this function would recurse through all negative numbers without ever reaching the base case of 0. As it is, the pattern matching is not complete: if a negative integer is passed to the fac function as an argument, the program will fail with a runtime error. A final case could check for this error condition and print an appropriate error message instead.
The "Prelude" is a number of small functions analogous to C's standard library. Using the Prelude and writing in the "point free" style of unspecified arguments, it becomes:
fac = product . enumFromTo 1
The above is close to mathematical definitions such as f = g o h (see function composition), and indeed, it is not an assignment of a value to a variable.
More complex examples
A simple RPN calculator:
calc = foldl f [] . words where f (x:y:zs) "+" = y+x:zs f (x:y:zs) "-" = y-x:zs f (x:y:zs) "*" = y*x:zs f (x:y:zs) "/" = y/x:zs f xs y = (read y :: Float):xs
A function which returns a stream of the Fibonacci numbers in linear time:
fibs = 0 : 1 : (zipWith (+) fibs (tail fibs))
The same function, written using GHC's parallel list comprehension syntax (GHC extensions must be enabled using a special command-line flag; see GHC's manual for more):
fibs = 0 : 1 : [ a+b | a <- fibs | b <- tail fibs ]
The factorial we saw previously can be written as a sequence of functions:
fac n = (foldl (.) id [\x -> x*k | k <- [1..n]]) 1
A remarkably concise function that returns the list of Hamming numbers in order:
hamming = 1 : map (*2) hamming # map (*3) hamming # map (*5) hamming where xxs@(x:xs) # yys@(y:ys) | x==y = x : xs#ys | x<y = x : xs#yys | x>y = y : xxs#ys
- See also List of hello world programs#Haskell for an example that prints text.
Criticism
Haskell has many advanced features not found in other programming languages; these features can and have been criticized for making the language more complex and difficult to understand. Some of the criticism directed against functional programming languages and non-mainstream programming languages are applicable to Haskell. In addition, there are complaints stemming from the purity of Haskell and its theoretical roots.
Jan-Willem Maessen in 2002 and Simon Peyton Jones in 2003 discuss the problems that come with lazy evaluation while they acknowledge the theoretical motivation for it. In addition to adding overhead, laziness makes it more difficult for programmers to reason about the performance of their code.
The language difficulties facing Haskell programmers have been recognized by Bastiaan Heeren, Daan Leijen, and Arjan van IJzendoorn in 2003. To achieve a language implementation that can give user-friendly error messages, they had to develop an advanced compiler (Helium) and limit some of the generality of Haskell, such as removing support for type classes.
Implementations
The following all comply fully, or very nearly, with the Haskell 98 standard, and are distributed under open source licences. There are currently no commercial Haskell implementations.
- Glasgow Haskell Compiler [1]. The Glasgow Haskell Compiler compiles to native code on a number of different architectures, and can also compile to C. GHC is probably the most popular Haskell compiler, and there are quite a few useful libraries (e.g. bindings to OpenGL) that will only work with GHC.
- Gofer An educational version of Haskell, Gofer was developed by Mark Jones. It was supplanted by HUGS.
- HBC [2] is another native-code Haskell compiler. It hasn't been actively developed for some time, but is still usable.
- Helium [3] is a newer dialect of Haskell. The focus is on making it easy to learn by providing clearer error messages. It currently lacks typeclasses, making it incompatible with many Haskell programs.
- Hugs [4] is a bytecode interpreter. It offers fast compilation of programs and reasonable execution speed. It also comes with a simple graphics library. Hugs is good for people learning the basics of Haskell, but is by no means a "toy" implementation. It is the most portable and lightweight of the Haskell implementations.
- Jhc [5] a haskell compiler written by John Meacham emphasising speed and efficiency of generated programs as well as exploration of new program transformations.
- nhc98 [6] is another bytecode compiler, but the bytecode runs significantly faster than with Hugs. Nhc98 focuses on minimising memory usage, and is a particularly good choice for older, slower machines.
Extensions
- O'Haskell is an extension of Haskell adding object-orientation and concurrent programming support.
References
- Simon Peyton Jones. Wearing the hair shirt: a retrospective on Haskell. Invited talk at POPL 2003.
- Jan-Willem Maessen. Eager Haskell: Resource-bounded execution yields efficient iteration. Proceedings of the 2002 ACM SIGPLAN workshop on Haskell.
- Bastiaan Heeren, Daan Leijen, Arjan van IJzendoorn. Helium, for learning Haskell. Proceedings of the 2003 ACM SIGPLAN workshop on Haskell.
External links
- The Haskell Home Page
- The Haskell Wiki
- A Gentle Introduction to Haskell 98 (pdf format)
- Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity
- The Evolution of a Haskell Programmer - a slightly humorous overview of different programming styles available in Haskell
- An Online Bibliography of Haskell Research
- Haskell Humor