This is an old revision of the document!


Crash course into Haskell's syntax

We use Haskell at PP in order to illustrate some functional programming concepts (or functional programming design patterns) which can be used in any functional or multi-paradigm lecture. These are:

  • programming with side-effect-free (or pure) functions
  • programming with higher-order functions
  • programming with Abstract (or Algebraic) Datatypes
  • programming with lazy evaluation

With this in mind, we point out that this is not a course about the Haskell language - although we will quite a few of its particular aspects (with IO being a distinguished omission). In this page you will find the subset of programming constructs which are used during the lecture.

Functions are defined as follows:

<function name> <param1> ... <param n> = <body expression>

For instance:

f x y = x + y

Anonymous functions can be defined as follows:

\<param1> ... <param n> -> <body expression>

For instance:

\x y -> x + y

Function calls are of the form:

<function name> <v1> ... <vn>

for a function with at least n parameters.

For instance:

 f 1 2 

Parentheses and $

It is a good practice (although not always necessary) to enclose a function call in parentheses, e.g. (f 1 2) instead of f 1 2. This actually makes the code more legible and avoids typing bugs.

To avoid cluttering of nested function calls, e.g. f (g (h x y)), the function application operator $ can be used. The type of $ is (a→b)→a→b, that is, it takes a function and an argument and applies the latter on the function. The previous call can be rewritten as:

f $ g $ h x y

You can also interpret $ as a means for enforcing precedence (i.e. first h is called, then g then f).

Functional composition is often a good alternative to $. For instance, the previous function call can be written as:

(f . g) (h x y)

Meaning that function (f . g) is called with argument (h x y). Note that (f . g . h) x y is not equivalent, and signifies the call of f . g . h with arguments x and y.

Infix and prefix

Usually (although not mandatory), functions are defined in prefix form (as seen in the previous examples). Some Haskell functions are infix (e.g. +, . or $). We can turn an infix function into a prefix one using parentheses. E.g. :t ($) or (+) 1 2. Similarly, we can turn an prefix function into an infix, using quasiquotes, e.g. 1 f 2 where f x y = x + y.

The basic datatypes used in the PP lecture are:

  • integers and floats (Integer and Float)
  • booleans (Bool)
  • char (Char)

The container types are:

  • lists ([a])
  • pairs ((a,b))
  • functions (a → b)

where a and b are type variables.

The base constructors for lists are:

  • [] :: [a] (the empty list)
  • (:) :: a → [a] → [a] (cons)

The list observers are:

  • head :: [a] → a
  • tail :: [a] → [a]

Other distinguished operators are:

  • (++) :: [a] → [a] → [a] (appending two lists)

The base constructor pairs is:

  • (,) :: a → b → (a,b)

Pair observers are:

  • fst :: (a,b) → a
  • snd :: (a,b) → b

The type String in Haskell is an alias for [Char].

A powerful mechanism in Haskell is pattern matching, which allows expressing