Programming in Haskell is very intuitive. For e.g Consider the following code which performs Quicksort

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

The qsort function when applied to an empty list will always return an empty list

The qsort function when applied to a list full of values will first pick a suitable value called a pivot. After that it will create 2 **sub-lists** which maybe sorted or unsorted. The first will contain all values less than the pivot and the other will contain all values greater than the pivot. It will then apply qsort function recursively to these **sub-lists**, till the final list has been sorted

# Lists in Haskell

A List is the most basic unit of manipulation used in Haskell.

```
Prelude> let numbers = [1,2,3,4]
Prelude> let strings = ["apple", "grapes", "orange", "banannas"]
```

Lists in Haskell are homogenous i.e we can have a list of strings or Integers, but we cannot have both the datatypes in a a single list. For e.g

`Prelude> let numbers = [1,2,3,"apples"]`

would be considered invalid by the compiler

Lists can be constructed in Haskell using the consing(:) operator. For e.g

```
Prelude> let nums = [1,2,3,4]
Prelude> nums
[1,2,3,4]
Prelude> 0:nums
[0,1,2,3,4
```

Note that the consing operator always expects a value:List . If we type something like 1:2 it will fail. However typing something like 1:[2] will result in a list of 2 elements being created as shown [1:2].