Thursday, April 30, 2009

Haskell - Lists

Haskell - Lists
Lists in Haskell are defined by square brackets, [].  In ghci, declaring a list is as simple as:
Prelude> [1,2,3]
[1,2,3]
Lists can be of any length, indeed you can type in the following (although I wouldn't recommend it!)
Prelude> [1,2, .. ]
[1,2,3,4,5,6,7,8,9,10,11,12....]
To create an empty list, type the following:
Prelude> []
[]
Lists must be all the same type, if we try to declare a list with the following, we will get an error
Prelude> [1,3,5,7,"nine"]

<interactive>:1:7:
No instance for (Num [Char])
arising from the literal `7' at <interactive>:1:7
Possible fix: add an instance declaration for (Num [Char])
In the expression: 7
In the expression: [1, 3, 5, 7, ....]
In the definition of `it': it = [1, 3, 5, ....]
What the interactive session is telling us here is there is a type incompatibility between Num and [Char] and suggests some possible fixes.
Operating on Lists
To concatonate two lists you use ++
Prelude> [1,2,3] ++ [4,5,6]
[1,2,3,4,5,6]
To add an element to a list use the cons operator :
Prelude> "Nate" : ["Bill","Ted","Stephen"]
["Nate","Bill","Ted","Stephen"]
List Comprehensions
List comprehensions are really a thing of beauty, although, the Haskell Wiki labels them as syntatic sugar.  I think they add an element of beauty and simplicity.  Comprehensions follow the basic syntax1:
[ e | q1 .., qn], n >=1
where the q1 qualifiers are:
  1. generators:  p <- e, where p is a pattern of type t and e is an expression of type t
  2. guards: an expression that evaluates to a bool
  3. local bindings: provide new definitions for use or subsquent generators or guards
Here's an example of how to generate a list of all even numbers between 1 and 50 using comprehensions:
Prelude> [ x | x <- [1 .. 50],even x]
[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50]
Granted, you can accomplish the same thing using arithimetic sequences:
[2,4 .. 50]

But take a look at how to solve Project Euler question #1 with list comprehensions:
Prelude> foldr (+) 0 [x | x <- [1 .. 999],x `mod` 3 == 0 || x `mod` 5 == 0]
Breaking down this line into parts,
Prelude> foldr (+) 0 [x | x <- [1 .. 999],x `mod` 3 == 0 || x `mod` 5 == 0]
x <- [1 .. 999] is a generator, it's using an arithimetic sequence to get all the numbers between 1 and 999.
Prelude> foldr (+) 0 [x | x <- [1 .. 999],x `mod` 3 == 0 || x `mod` 5 == 0]
x `mod` 3 == 0 || x `mod` 5 == 0 is a guard or predicate.  Only when this expressions is true is it "passed" to the new list.
Prelude> foldr (+) 0 [x | x <- [1 .. 999],x `mod` 3 == 0 || x `mod` 5 == 0]
x is the new list of all the numbers between 1 and 999 that satisfy the predicate.  Then, x becomes part of the last expression, the foldr function.
foldr, or reduce, applys the the operator + in this case to the seed value 0 and each element in the list.

No comments: