Programmieren in Haskell Programmieren mit Listen Programmieren in Haskell 1 Was wir heute machen • Eigener Listen-Datentyp • Eine Sortierfunktion • Nützliche Listenfunktionen Programmieren in Haskell 2 Ein eigener Listen-Datentyp data List a = Nil | Cons a (List a) deriving (Show,Eq) Listen sind dann zum Beispiel: Nil :: List a Cons 1 (Cons 2 (Cons 3 Nil)) :: Num a => List a Cons "hallo" (Cons "welt" Nil) :: List [Char] Programmieren in Haskell 3 Spezifikation des Sortierproblems Gewünscht ist eine Funktion sortList :: Ord a => List a -> List a, so daß für jede Liste xs :: List a (mit Ord a), die Elemente von sortList xs geordnet sind, keine Elemente hinzukommen und keine verlorengehen. Programmieren in Haskell 4 Sortieren durch Einfügen isortList :: Ord a => List a -> List a isortList Nil = Nil isortList (Cons x xs) = insertList x (isortList xs) where insertList insertList | x <= y | x > y x x = = Nil = Cons x Nil (Cons y ys) Cons x (Cons y ys) Cons y (insertList x ys) Beispiel: sortList (Cons 1 (Cons 4 (Cons 2 Nil))) => Cons 1 (Cons 2 (Cons 4 Nil)) Programmieren in Haskell 5 Kopf und Restliste headList :: List a -> a headList Nil = error "headList not defined for empty lists" headList (Cons x xs) = x tailList :: List a -> List a tailList Nil = error "tailList not defined for empty lists" tailList (Cons x xs) = xs Programmieren in Haskell 6 Länge, Summe und Produkt lengthList :: Num a => List b -> a lengthList Nil = 0 lengthList (Cons x xs) = 1 + lengthList xs sumList :: Num a => List a -> a sumList Nil = 0 sumList (Cons x xs) = x + sumList xs productList :: Num a => List a -> a productList Nil = 1 productList (Cons x xs) = x * productList xs Programmieren in Haskell 7 Aufzählungen enumFromToList :: (Enum a, Ord a) => a -> a -> List a enumFromToList a b | a > b = Nil | a == b = Cons a Nil | a < b = Cons a (enumFromToList (succ a) b) Beispiele: enumFromToList 1 5 => Cons 1 (Cons 2 (Cons 3 (Cons 4 (Cons 5 Nil)))) enumFromToList 5 4 => Nil enumFromToList ’a’ ’d’ => Cons ’a’ (Cons ’b’ (Cons ’c’ (Cons ’d’ Nil))) Programmieren in Haskell 8 Fakultät factorialList :: Integral a => a -> a factorialList n | n < 0 = error "factorialList not defined for negative values" | otherwise = productList (enumFromToList 1 n) Beispiele: factorialList 4 => 24, factorialList 0 => 1 Alternative Definition ohne Listen: factorial :: factorial n | n < 0 = | n == 0 = | n > 0 = Programmieren in Haskell Integral a => a -> a error "factorial not defined for negative values" 1 n * factorial (n-1) 9 Append appendList :: List a -> List a -> List a appendList Nil ys = ys appendList (Cons x xs) ys = Cons x (appendList xs ys) Beispiel: appendList (enumFromToList 1 5) (enumFromToList 6 10) == enumFromToList 1 10 => True Programmieren in Haskell 10 Reverse reverseListSlow :: List a -> List a reverseListSlow Nil = Nil reverseListSlow (Cons x xs) = appendList (reverseListSlow xs) (Cons x Nil) Beispiel: reverseListSlow (enumFromToList 1 3) => Cons 3 (Cons 2 (Cons 1 Nil)) Programmieren in Haskell 11 Jetzt alle! isortList (reverseListSlow (enumFromToList 1 90)) => Cons 1 (Cons 2 (Cons 3 (Cons 4 (Cons 5 (Cons 6 (Cons 7 (Cons 8 (Cons 9 (Cons 10 (Cons 11 (Cons 12 (Cons 13 (Cons 14 (Cons 15 (Cons 16 (Cons 17 (Cons 18 (Cons 19 (Cons 20 (Cons 21 (Cons 22 (Cons 23 (Cons 24 (Cons 25 (Cons 26 (Cons 27 (Cons 28 (Cons 29 (Cons 30 (Cons 31 (Cons 32 (Cons 33 (Cons 34 (Cons 35 (Cons 36 (Cons 37 (Cons 38 (Cons 39 (Cons 40 (Cons 41 (Cons 42 (Cons 43 (Cons 44 (Cons 45 (Cons 46 (Cons 47 (Cons 48 (Cons 49 (Cons 50 (Cons 51 (Cons 52 (Cons 53 (Cons 54 (Cons 55 (Cons 56 (Cons 57 (Cons 58 (Cons 59 (Cons 60 (Cons 61 (Cons 62 (Cons 63 (Cons 64 (Cons 65 (Cons 66 (Cons 67 (Cons 68 (Cons 69 (Cons 70 (Cons 71 (Cons 72 (Cons 73 (Cons 74 (Cons 75 (Cons 76 (Cons 77 (Cons 78 (Cons 79 (Cons 80 (Cons 81 (Cons 82 (Cons 83 (Cons 84 (Cons 85 (Cons 86 (Cons 87 (Cons 88 (Cons 89 (Cons 90 Nil))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) )))))))))))))))))))))))))))))) Programmieren in Haskell 12 Take takeList takeList | n < takeList takeList | n == | n > Programmieren in Haskell :: Integral a => a -> List b -> List b n xs 0 = error "takeList not defined for negative values" n Nil = Nil n (Cons x xs) 0 = Nil 0 = Cons x (takeList (n-1) xs) 13 Beispiele: takeList 3 (enumFromToList 1 10) => Cons 1 (Cons 2 (Cons 3 Nil)) takeList 3 (enumFromToList 1 2) => Cons 1 (Cons 2 Nil) takeList 0 (enumFromToList 1 10) => Nil takeList (-5) (enumFromToList 1 10) => Program error: takeList not defined for negative values Programmieren in Haskell 14 Drop dropList dropList | n < dropList dropList | n == | n > :: Integral a => a -> List b -> List b n xs 0 = error "dropList not defined for negative values" n Nil = Nil n (Cons x xs) 0 = (Cons x xs) 0 = dropList (n-1) xs Beispiele: dropList 3 (enumFromToList 1 10) => Cons 4 (Cons 5 (Cons 6 (Cons 7 (Cons 8 (Cons 9 (Cons 10 Nil)))))) dropList 10 (enumFromToList 1 5) => Nil Programmieren in Haskell 15 Map mapList :: (a -> b) -> List a -> List b mapList f Nil = Nil mapList f (Cons x xs) = Cons (f x) (mapList f xs) Beispiel: mapList (+1) (enumFromToList 1 4) Cons 2 (Cons 3 (Cons 4 (Cons 5 Nil))) Programmieren in Haskell 16 Filter filterList :: (a -> Bool) -> List a -> List a filterList p Nil = Nil filterList p (Cons x xs) | p x = Cons x (filterList p xs) | otherwise = filterList p xs Beispiel: filterList (>5) (enumFromToList 1 10) => Cons 6 (Cons 7 (Cons 8 (Cons 9 (Cons 10 Nil)))) Programmieren in Haskell 17 Filter-Beispiel oddList :: Integral a => List a -> List a oddList = filterList odd where odd x = x ‘mod‘ 2 /= 0 Beispiel: oddList (enumFromToList 1 10) => Cons 1 (Cons 3 (Cons 5 (Cons 7 (Cons 9 Nil)))) Alternative ohne filterList oddListBoring oddListBoring oddListBoring | x ‘mod‘ 2 | otherwise Programmieren in Haskell :: Integral a => List a -> List a Nil = Nil (Cons x xs) /= 0 = Cons x (oddListBoring xs) = oddListBoring xs 18 Concat concatList :: List (List a) -> List a concatList Nil = Nil concatList (Cons xs xss) = appendList xs (concatList xss) Beispiel: concatList (Cons (enumFromToList 1 3) (Cons (enumFromToList 4 5) Nil)) => Cons 1 (Cons 2 (Cons 3 (Cons 4 (Cons 5 Nil)))) Programmieren in Haskell 19