Programmieren in Haskell Programmieren mit Listen II Programmieren in Haskell 1 Was wir heute machen • Von eigenen Listen zu eingebauten • Eine Sortierfunktion • Nützliche Listenfunktionen • Listenzucker und Listenbeschreibungen • Primzahlen • Noch eine Sortierfunktion • Semantik von Listenbeschreibungen Programmieren in Haskell 2 Von eigenen Listen zu eingebauten data List a = Nil | Cons a (List a) data [a] = [] | (a:[a]) -- Pseudocode Nil :: List a Cons 1 (Cons 2 (Cons 3 Nil)) :: Num a => List a Cons "hallo" (Cons "welt" Nil) :: List [Char] [] :: [a] 1:2:3:[] :: Num a => [a] "hallo":"welt":[] :: [[Char]] -- "normale" infix-Schreibweise -- ebenso (:) 1 ((:) 2 ((:) 3 [])) :: Num a => [a] Programmieren in Haskell -- prefix-Schreibweise! 3 Sortieren durch Einfügen isort :: Ord a => [a] -> [a] isort [] = [] isort (x:xs) = insert x (isort xs) where insert x [] = [x] insert x (y:ys) | x <= y = x:y:ys | x > y = y:(insert x ys) Programmieren in Haskell 4 Nützliche Listenfunktionen head’ :: [a] -> a head’ [] = error "head’ not defined for empty lists" head’ (x:xs) = x tail’ :: [a] -> [a] tail’ [] = error "tail’ not defined for empty lists" tail’ (x:xs) = xs Programmieren in Haskell 5 length’ :: Num a => [b] -> a length’ [] = 0 length’ (x:xs) = 1 + length’ xs sum’ :: Num a => [a] -> a sum’ [] = 0 sum’ (x:xs) = x + sum’ xs product’ :: Num a => [a] -> a product’ [] = 1 product’ (x:xs) = x * product’ xs Programmieren in Haskell 6 enumFromTo’ :: (Enum a, Ord a) => a -> a -> [a] enumFromTo’ a b | a > b = [] | a == b = [a] | a < b = a:(enumFromTo’ (succ a) b) factorial’ :: Integral a => a -> a factorial’ n | n < 0 = error "factorial’ not defined for negative values" | otherwise = product’ (enumFromTo’ 1 n) Programmieren in Haskell 7 append’ :: [a] -> [a] -> [a] append’ [] ys = ys append’ (x:xs) ys = x:(append’ xs ys) reverse’Slow :: [a] -> [a] reverse’Slow [] = [] reverse’Slow (x:xs) = append’ (reverse’Slow xs) [x] schneller: reverse’ :: [a] -> [a] reverse’ xs = rev [] xs where rev as [] = as rev as (x:xs) = rev (x:as) xs Programmieren in Haskell 8 take’ take’ | n take’ take’ | n | n :: Integral a => a -> [b] -> [b] n xs < 0 = error "take’ not defined for negative values" n [] = [] n (x:xs) == 0 = [] > 0 = x:(take’ (n-1) xs) Programmieren in Haskell 9 drop’ drop’ | n drop’ drop’ | n | n :: Integral a => a -> [b] -> [b] n xs < 0 = error "drop’ not defined for negative values" n [] = [] n (x:xs) == 0 = x:xs > 0 = drop’ (n-1) xs Programmieren in Haskell 10 map’ :: (a -> b) -> [a] -> [b] map’ f [] = [] map’ f (x:xs) = (f x):(map’ f xs) filter’ :: (a -> Bool) -> [a] -> [a] filter’ p [] = [] filter’ p (x:xs) | p x = x:filter’ p xs | otherwise = filter’ p xs Programmieren in Haskell 11 concat’ :: [[a]] -> [a] concat’ [] = [] concat’ (xs:xss) = append’ xs (concat’ xss) Programmieren in Haskell 12 Listen-Zucker [1 ..] Liste der positiven, ganzen Zahlen [1 .. 99] Liste der positiven, ganzen Zahlen bis einschließlich 99 [1, 3 ..] Liste der ungeraden, positiven Zahlen [1, 3 .. 99] Liste der ungeraden, positiven Zahlen bis einschließlich 99 Programmieren in Haskell 13 Listenbeschreibungen squares = [n*n | n <- [0..99]] map f xs = [f a | a <- xs] a ‘elem‘ xs = or [a == b | b <- xs] Programmieren in Haskell 14 Primzahlen primesSlow :: Integral a => [a] primesSlow = [n | n <- [2..], divisors n == [1,n]] where divisors :: Integral a => a -> [a] divisors n = [d | d <- [1..n], n ‘mod‘ d == 0] Programmieren in Haskell 15 Sieb des Eratosthenes primes :: Integral a => [a] primes = sieve [2..] where sieve :: Integral a => [a] -> [a] sieve (a:xs) = a:sieve [n | n <- xs, n ‘mod‘ a /= 0] Programmieren in Haskell 16 Quicksort qsort :: Ord a => [a] -> [a] qsort [] = [] qsort (a:xs) = qsort [b | b <- xs, b < a] ++ [a] ++ qsort [b | b <- xs, b >= a] Programmieren in Haskell 17 Semantik von Listenbeschreibungen Programmieren in Haskell [ e | p <- l ] = map (\p -> e) l [ e | b ] = if b then [e] else [] [ e | let ds ] = let ds in [e] [ e | q1 , q2 ] = concat [ [ e | q2 ] | q1 ] 18