1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
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
|