19 Oct

Lists

Empty list: []

Prepending:

> 1 : [2, 3]
[1, 2, 3]

> 'a' : "bcd"
"abcd"

Appending/concatenating:

> [1, 2] ++ [3, 4]
[1, 2, 3, 4]

> [1] ++ [2, 3]
[1, 2, 3]

> "ab" ++ "cd"
"abcd"

Extracting:

> head [1, 2, 3]
1

> tail [1, 2, 3]
[2, 3]

> last [1, 2, 3]
3

> drop 2 [1, 2, 3, 4, 5]  -- last two elements
[4, 5]

> "abc" !! 1  -- arbitrary index
'b' -- zero-based index

Signature types:

squares :: [Int] -> [Int]  -- takes a list of integers and returns a list of integers

Ranges:

> [1..5]
[1,2,3,4,5]

> [5..1]  -- won't implicitly work for reverse
[]

> [1..]
[1, 2, 3, 4, 5, 6, 7, ...]  -- will run to infinity

> ['a'..'e']  -- letters too
"abcde"

Recursion

Square every element: squares [1, 2, 3] is [1, 4, 9]

Manipulating elements in a list one by one, the following are equivalent:

-- descriptive, list comprehension
squares xs = [x^2 | x <- xs]  -- x^2 is equivalent to x*x

-- equational recursion
squares []     = []
squares (x:xs) = x^2 : squares xs  -- list with head x and tail xs

-- conditional recursion
squares l =
  if l == [] then []
  else x^2 : squares xs
    where x  = head l
          xs = tail l

-- conditional recursion (with let..in)
squares l =
  if l == [] then []
  else let x  = head l
           xs = tail l
       in x^2 : squares xs

Square only even elements: squareEvens [1, 2, 3, 4] is [4, 16]

Manipulating elements if they match a condition, the following are equivalent:

-- descriptive
squareEvens xs = [x^2 | x <- xs, even x]  -- 'even' is a built-in equivalent to (x `mod` 2 == 0)

-- pattern matching
squareEvens [] = []
squareEvens (x:xs)
  | even x    = x : squareEvens xs
  | otherwise = squareEvens xs