I wasn’t really sure of quite how to start this off. I finally decided to just dive right in with a simple function definition, and then give you a bit of a tour of how Haskell works by showing the different ways of implementing it.

So let’s dive right in a take a look at a very simple Haskell definition of the factorial function:

fact n = if n == 0

then 1

else n * fact (n – 1)

This is the classic implementation of the factorial. Some things to notice:

1. In Haskell, a function definition uses no keywords. Just “`name params = impl`”.

2. Function application is written by putting things side by side. So to apply

the factorial function to `x`, we just write `fact x`. Parens are only used for

managing precedence. The parens in “`fact (n – 1)`” aren’t there because the

function parameters need to be wrapped in parens, but because otherwise,

the default precedence rules would parse it as “`(fact n) – 1`”.

3. Haskell uses infix syntax for most mathematical operations. That doesn’t mean that

they’re special: they’re just an alternative way of writing a binary function

invocation. You can define your own mathematical operators using normal function

definitions.

4. There are no explicit grouping constructs in Haskell: no “{/}”, no “begin/end”. Haskell’s

formal syntax uses braces, but the language defines how to translate indentation changes

into braces; in practice, just indenting the code takes care of grouping.

That implementation of factorial, while correct, is not how most Haskell programmers would implement

it. Haskell includes a feature called *pattern matching*, and most programmers would use

pattern matching rather than the `if/then` statement for a case like that. Pattern matching separates

things and often makes them easier to read. The basic idea of pattern matching in function

definitions is that you can write what *look like* multiple versions of the function, each of which

uses a different set of patterns for its parameters (we’ll talk more about what patterns look like in

detail in a later post); the different cases are separated not just by something like a conditional statement, but they’re completely separated at the definition level. The case that matches the values at the point of call is the one that is actually invoked. So here’s a more stylistically correct version of the factorial:

fact 0 = 1

fact n = n * fact (n – 1)

In the semantics of Haskell, those two are completely equivalent. In fact, the deep semantics of Haskell are based on pattern matching – so it’s more correct to say that the if/then/else version

is translated into the pattern matching version than vice-versa! In fact, both will basically expand to the Haskell pattern-matching primitive called the “`case`” statement, which selects from

among a list of patterns: *(Note: I originally screwed up the following, by putting a single “=” instead of a “==” inside the comparison. Stupid error, and since this was only written to explain things, I didn’t actually run it. Thanks to pseudonym for pointing out the error.)*

fact n = case (n==0) of

True -> 1

False -> n * fact (n – 1)

Another way of writing the same thing is to use Haskell’s list type. Lists are a very fundamental type in Haskell. They’re similar to lists in Lisp, except that all of the elements of a list must have the same type. A list is written between square brackets, with the values in the list written

inside, separated by commas, like:

[1, 2, 3, 4, 5]

As in lisp, the list is actually formed from pairs, where the first element of the pair is

a value in the list, and the second value is the rest of the list. Pairs are *constructed* in Haskell using “`:`”, so the list could also be written in the following ways:

1 : [2, 3, 4, 5]

1 : 2 : [3, 4, 5]

1 : 2 : 3 : 4 : 5 : []

If you want a list of integers in a specific range, there’s a shorthand for it using “`..`”. To generate the list of values from `x` to `y`, you can write:

[ x .. y ]

Getting back to our factorial function, the factorial of a number “n” is the product of all of the

integers from 1 to n. So another way of saying that is that the factorial is the result of taking the list of all integers from 1 to n, and multiplying them together:

listfact n = listProduct [1 .. n]

But that doesn’t work, because we haven’t defined `listProduct` yet. Fortunately, Haskell provides

a ton of useful list functions. One of them, “`foldl`”, takes a function *f*, an initial value *i*,

and a list *[l_{1}, l_{2},...,l_{n}]*, and basically does *f(l_{n}(…f(l_{2}, f(i,l_{1}))))*. So we can use `foldl` with the multiply

function to multiply the elements of the list together. The only problem is that multiplication is written as an infix operator, not a function. In Haskell, the solution to *that* is simple: an infix operator is just fancy syntax for a function call; to get the function, you just put the operator

into parens. So the multiplication *function* is written “`(*)`”. So let’s add a definition of `listProduct` using that; we’ll do it using a *`where`* clause, which allows us to define

variables or functions that are local to the scope of the enclosing function definition:

listfact n = listProduct [ 1 .. n ]

where listProduct lst = foldl (*) 1 lst

I need to explain one more list function before moving on. There’s a function called “`zipWith`” for performing an operation pairwise on two lists. For example, given the lists “`[1,2,3,4,5]`” and “`[2,4,6,8,10]`”, “`zipWith (+) [1,2,3,4,5] [2,4,6,8,10]`” would result in “`[3,6,9,12,15]`”.

Now we’re going to jump into something that’s going to seem really strange. One of the fundamental

properties of how Haskell runs a program is that Haskell is a *lazy* language. What that means is

that no expression is actually evaluated until its value is *needed*. So you can do things like

create *infinite* lists – since no part of the list is computed until it’s needed. So we can do

things like define the fibonacci series – the *complete* fibonacci series, using:

fiblist = 0 : 1 : (zipWith (+) fiblist (tail fiblist))

This looks incredibly strange. But if we tease it apart a bit, it’s really pretty simple:

1. The first element of the fibonacci series is “0”

2. The second element of the fibonacci series is “1”

3. For the rest of the series, take the full fibonacci list, and line up the two copies

of it, offset by one (the full list, and the list without the first element), and add the

values pairwise.

That third step is the tricky one. It relies on the *laziness* of Haskell:

Haskell won’t compute the *nth* element of the list until you *explicitly*

reference it; until then, it just keeps around the *unevaluated* code for computing the part of the list you haven’t looked at. So when you try to look at the *n*th value, it will compute the list *only up to* the *n*th value. So the actual computed part of the list is always finite – but you can act as if it wasn’t. You can treat that list *as if* it really were infinite – and retrieve any value from it that you want. Once it’s been referenced, then the list up to where you looked is concrete – the computations *won’t* be repeated. But the last tail of the list will always be an

unevaluated expression that generates the *next* pair of the list – and *that* pair will always be the next element of the list, and an evaluated expression for the pair after it.

Just to make sure that the way that “`zipWith`” is working in “`fiblist`” is clear, let’s look

at a prefix of the parameters to `zipWith`, and the result. (Remember that those three are all

actually the same list! The diagonals from bottom left moving up and right are the same list elements.)

fiblist = [0 1 1 2 3 5 8 ...]

tail fiblist = [1 1 2 3 5 8 ... ]

zipWith (+) = [1 2 3 5 8 13 ... ]

Given that list, we can find the *n*th element of the list very easily; the *n*th element of a list *l* can be retrieved with “`l !! n`”, so, the fibonacci function to get the *n*th fibonacci

number would be:

fib n = fiblist !! n

And using a very similar trick, we can do factorials the same way:

factlist = 1 : (zipWith (*) [1..] factlist)

factl n = factlist !! n

The nice thing about doing factorial this way is that the values of all of the factorials *less than* *n* are also computed and remember – so the next time you take a factorial, you don’t need to

repeat those multiplications.