Gentle Introduction to Haskell 98, Online Supplement Part 5 Covers Sections 2.5.1, 2.5.2 > module Part6() where Section: 2.5.1 List Comprehensions and Arithmetic Sequences Warning: brackets in Haskell are used in three different sorts of expressions: lists, as in [a,b,c], sequences (distinguished by the ..), as in [1..2], and list comprehensions (distinguished by the bar: |), as in [x+1 | x <- xs, x > 1]. Before list comprehensions, consider sequences: > e1 :: [Int] > e1 = [1..10] -- Step is 1 > e2 :: [Int] > e2 = [1,3..10] -- Step is 3 - 1 > e3 :: [Int] > e3 = [1,-1.. -10] -- The space before - is necessary! > e4 :: [Char] > e4 = ['a'..'z'] -- This works on chars too We'll avoid infinite sequences like [1..] for now. If you print one, use C-c i to interrupt the Haskell program. List comprehensions are very similar to nested loops. They return a list of values generated by the expression inside the loop. The filter expressions are similar to conditionals in the loop. This function does nothing at all! It just scans through a list and copies it into a new one. > doNothing :: [a] -> [a] > doNothing l = [x | x <- l] Adding a filter to the previous function allows only selected elements to be generated. This is similar to what is done in quicksort. > positives :: [Int] -> [Int] > positives l = [x | x <- l, x > 0] > e5 = positives [2,-4,5,6,-5,3] Now the full quicksort function. > quicksort :: [Char] -> [Char] -- Use Char just to be different! > quicksort [] = [] > quicksort (x:xs) = quicksort [y | y <- xs, y <= x] ++ > [x] ++ > quicksort [y | y <- xs, y > x] > e6 = quicksort "Why use Haskell?" Now for some nested loops. Each generator, <-, adds another level of nesting to the loop. The variable introduced by each generator can be used in each following generator; all variables can be used in the generated expression: > e7 :: [(Int,Int)] > e7 = [(x,y) | x <- [1..5], y <- [x..5]] Now add some guards: (the /= function is `not equal') > e8 :: [(Int,Int)] > e8 = [(x,y) | x <- [1..7], x /= 5, y <- [x..8] , x*y /= 12] This is the same as the loop: (going to a psuedo Algol notation) for x := 1 to 7 do if x <> 5 then for y := x to 8 do if x*y <> 12 generate (x,y) Section: 2.5.2 Strings > e9 = "hello" ++ " world" Continued in part7.lhs