# haskell solutions

Post on 26-Jun-2015

218 views

Embed Size (px)

TRANSCRIPT

Programming in Haskell Solutions to ExercisesGraham Hutton University of Nottingham

ContentsChapter 1 - Introduction Chapter 2 - First steps Chapter 3 - Types and classes Chapter 4 - Dening functions Chapter 5 - List comprehensions Chapter 6 - Recursive functions Chapter 7 - Higher-order functions Chapter 8 - Functional parsers Chapter 9 - Interactive programs Chapter 10 - Declaring types and classes Chapter 11 - The countdown problem Chapter 12 - Lazy evaluation Chapter 13 - Reasoning about programs 1 3 4 5 7 9 13 15 19 21 23 24 26

Chapter 1 - IntroductionExercise 1= = = = = or = = = = = = double (double 2) { applying the outer double } (double 2) + (double 2) { applying the second double } (double 2) + (2 + 2) { applying the second + } (double 2) + 4 { applying double } (2 + 2) + 4 { applying the rst + } 4+4 { applying + } 8 double (double 2) { applying the inner double } double (2 + 2) { applying double } (2 + 2) + (2 + 2) { applying the rst + } 4 + (2 + 2) { applying the second + } 4+4 { applying + } 8

There are a number of other answers too.

Exercise 2sum [x ] { applying sum } x + sum [ ] = { applying sum } x +0 = { applying + } x =

Exercise 3(1) product [ ] = product (x : xs) = 1 x product xs

1

(2) product [2, 3, 4] { applying product } 2 (product [3, 4]) { applying product } 2 (3 product [4]) { applying product } 2 (3 (4 product [ ])) { applying product } 2 (3 (4 1)) { applying } 24

= = = = =

Exercise 4Replace the second equation by qsort (x : xs) = qsort larger + [x ] + qsort smaller + + That is, just swap the occurrences of smaller and larger .

Exercise 5Duplicate elements are removed from the sorted list. For example: = = = = = qsort [2, 2, 3, 1, 1] { applying qsort } qsort [1, 1] + [2] + qsort [3] + + { applying qsort } (qsort [ ] + [1] + qsort [ ]) + [2] + (qsort [ ] + [3] + qsort [ ]) + + + + + + { applying qsort } ([ ] + [1] + [ ]) + [2] + ([ ] + [3] + [ ]) + + + + + + { applying + } + [1] + [2] + [3] + + { applying + } + [1, 2, 3]

2

Chapter 2 - First stepsExercise 1(2 3) 4 (2 3) + (4 5) 2 + (3 (4 5))

Exercise 2No solution required.

Exercise 3n = a div length xs where a = 10 xs = [1, 2, 3, 4, 5]

Exercise 4last xs or last xs = xs !! (length xs 1) = head (reverse xs)

Exercise 5init xs or init xs = reverse (tail (reverse xs)) = take (length xs 1) xs

3

Chapter 3 - Types and classesExercise 1[Char ] (Char , Char , Char ) [(Bool , Char )] ([Bool ], [Char ]) [[a ] [a ]]

Exercise 2[a ] a (a, b) (b, a) a b (a, b) Num a a a Eq a [a ] Bool (a a) a a

Exercise 3No solution required.

Exercise 4In general, checking if two functions are equal requires enumerating all possible argument values, and checking if the functions give the same result for each of these values. For functions with a very large (or innite) number of argument values, such as values of type Int or Integer, this is not feasible. However, for small numbers of argument values, such as values of type of type Bool , it is feasible.

4

Chapter 4 - Dening functionsExercise 1halve xs or halve xs = (take n xs, drop n xs) where n = length xs div 2 = splitAt (length xs div 2) xs

Exercise 2(a) safetail xs (b) safetail xs | null xs | otherwise (c) safetail [ ] safetail xs or safetail [ ] = safetail ( : xs) = [] xs = = [] tail xs = = [] tail xs = if null xs then [ ] else tail xs

Exercise 3(1) False False False True True False True True (2) False False (3) False b True (4) b c | b == c | otherwise = = b True = = b True = False = True = = = = False True True True

5

Exercise 4ab = if a then if b then True else False else False

Exercise 5ab = if a then b else False

Exercise 6mult = x (y (z x y z ))

6

Chapter 5 - List comprehensionsExercise 1sum [x 2 | x [1 . . 100]]

Exercise 2replicate n x = [x | [1 . . n ]]

Exercise 3pyths n = [(x , y, z ) | x y z x [1 . . n ], [1 . . n ], [1 . . n ], 2 + y 2 == z 2]

Exercise 4perfects n = [x | x [1 . . n ], sum (init (factors x )) == x ]

Exercise 5concat [[(x , y) | y [4, 5, 6]] | x [1, 2, 3]]

Exercise 6positions x xs = nd x (zip xs [0 . . n ]) where n = length xs 1

Exercise 7scalarproduct xs ys = sum [x y | (x , y) zip xs ys ]

Exercise 8shift shift n c | isLower c | isUpper c | otherwise freqs freqs xs :: = = = :: = Int Char Char int2low ((low2int c + n) mod 26) int2upp ((upp2int c + n) mod 26) c String [Float ] [percent (count x xs ) n | x [a . . z]] where xs = map toLower xs n = letters xs Char Int ord c ord a 7

low2int low2int c

:: =

int2low int2low n upp2int upp2int c int2upp int2upp n letters letters xs

:: = :: = :: = :: =

Int Char chr (ord a + n) Char Int ord c ord A Int Char chr (ord A + n) String Int length [x | x xs, isAlpha x ]

8

Chapter 6 - Recursive functionsExercise 1(1) m 0 = 1 m (n + 1) = m m n (2) = = = = = 23 { applying } 2 (2 2) { applying } 2 (2 (2 1)) { applying } 2 (2 (2 (2 0))) { applying } 2 (2 (2 1)) { applying } 8

Exercise 2(1) = = = = = length [1, 2, 3] { applying length } 1 + length [2, 3] { applying length } 1 + (1 + length [3]) { applying length } 1 + (1 + (1 + length [ ])) { applying length } 1 + (1 + (1 + 0)) { applying + } 3

(2) = drop 3 [1, 2, 3, 4, 5] { applying drop drop 2 [2, 3, 4, 5] = { applying drop drop 1 [3, 4, 5] = { applying drop drop 0 [4, 5] = { applying drop [4, 5] } } } }

9

(3) init [1, 2, 3] { applying init } 1 : init [2, 3] = { applying init } 1 : 2 : init [3] = { applying init } 1 :2 : [] = { list notation } [1, 2]

=

Exercise 3and [ ] and (b : bs) concat [ ] concat (xs : xss) replicate 0 replicate (n + 1) x (x : ) !! 0 ( : xs) !! (n + 1) elem x [ ] elem x (y : ys) | x == y | otherwise = = = = = = = = = = = True b and bs [] xs + concat xss + [] x : replicate n x x xs !! n False True elem x ys

Exercise 4merge [ ] ys merge xs [ ] merge (x : xs) (y : ys) = ys = xs = if x y then x : merge xs (y : ys) else y : merge (x : xs) ys

Exercise 5halve xs = splitAt (length xs div 2) xs

msort [ ] = [] msort [x ] = [x ] msort xs = merge (msort ys) (msort zs) where (ys, zs) = halve xs

10

Exercise 6.1Step 1: dene the type sum :: [Int ] Int = = Step 2: enumerate the cases sum [ ] sum (x : xs)

Step 3: dene the simple cases sum [ ] sum (x : xs) = 0 =

Step 4: dene the other cases sum [ ] sum (x : xs) = 0 = x + sum xs

Step 5: generalise and simplify sum sum :: = Num a [a ] a foldr (+) 0

Exercise 6.2Step 1: dene the type take :: Int [a ] [a ] 0 [] 0 (x : xs) (n + 1) [ ] (n + 1) (x : xs) = = = = Step 2: enumerate the cases take take take take

Step 3: dene the simple cases take take take take 0 [] 0 (x : xs) (n + 1) [ ] (n + 1) (x : xs) = = = = [] [] []

Step 4: dene the other cases take take take take 0 [] 0 (x : xs) (n + 1) [ ] (n + 1) (x : xs) = = = = [] [] [] x : take n xs Int [a ] [a ] [] [] x : take n xs

Step 5: generalise and simplify take :: = take 0 take (n + 1) [ ] = take (n + 1) (x : xs) =

11

Exercise 6.3Step 1: dene the type last :: [a ] [a ] Step 2: enumerate the cases last (x : xs) = Step 3: dene the simple cases last (x : xs) | null xs | otherwise Step 4: dene the other cases last (x : xs) | null xs | otherwise Step 5: generalise and simplify last :: last [x ] = last ( : xs) = [a ] [a ] x last xs = x = last xs = x =

12

Chapter 7 - Higher-order functionsExercise 1map f (lter p xs)

Exercise 2all p any p = = and map p or map p

takeWhile [ ] = [ ] takeWhile p (x : xs) |px = x : takeWhile p xs | otherwise = [ ] dropWhile [ ] dropWhile p (x |px | otherwise = [] : xs) = dropWhile p xs = x : xs

Exercise 3map f lter p = = foldr (x xs f x : xs) [ ] foldr (x xs if p x then x : xs else xs) [ ]

Exercise 4dec2nat = foldl (x y 10 x + y) 0

Exercise 5The functions being composed do not all have the same types. For example: sum map (2) lter even :: [Int ] Int :: [Int ] [Int ] :: [Int ] [Int ]

Exercise 6curry curry f uncurry uncurry f :: = :: = ((a, b) c) (a b c) x y f (x , y) (a b c) ((a, b) c) (x , y) f x y

13

Exercise 7chop8 map f iterate f = = = unfold null (take 8) (drop 8) unfold null (f head ) tail unfold (const False) id f

Exercise 8encode encode decode decode addparity addparity bs :: = :: = :: = String [Bit ] concat map (addparity make8 int2bin ord ) [Bit ] String map (chr bin2int checkparity ) chop9 [Bit ] [Bit ] (parity bs) : bs [Bit ] Bit 1 0 [Bit ] [[Bit ]] [] take 9 bits : chop9 (drop 9 bits) [Bit ] [Bit ] bs error "parity mismatch"

parity :: parity bs | odd (sum bs) = | otherwise = chop9 chop9 [ ] chop9 bits checkparity checkparity (b : bs) | b == parity bs | otherwise :: = = :: = =

Exercise 9No solution required.

14

Chapter 8 - Functional parsersExercise 1int = do char - n nat return (n) + +nat +

Exercise 2comment = do string "--" many (sat (= \n)) return ()

Exercise 3(1) expr KK KK uuu zu % expr exprI + II u I$ uu zu expr expr + term term term factor factor nat 2 (2) expr I ss III yss $ exprI expr + uu III zuu $ expr expr + term factor nat 2 term factor nat 3 term factor nat 4 factor nat 3 nat 4

15

Exercise 4(1) expr I III uuu $ zu expr + term factor term factor nat nat 2 3 (2) expr termI t II I$ yttt factor termG GGG ww G# {ww factor nat term factor nat 2 nat 3 4 (3) expr K ss KKK yss % expr + term factorI term III uuu II $ zuuu expr ) factor ( JJJ tt JJ zttt $ expr + term nat factor nat 2 term factor nat 3 4

16