3Datentypdefi Programmiersprache 3 Eine Eineeinfache einfache Programmiersprache3.1 Datentypen 3.1.1 nitionen3.1.2 Typsynonyme 3.1.3 Typdeklarationen, Typprüfung und Typinferenz 3.1.4 Typklassen und Typkontexte 3.2 Wertdefi nitionen 3.2.1 Musterund Funktionsbindungen 3.2.2 Bewachte Gleichungen 3.2.3 GleichungenVollständige mit lokalen Defi 3.2.4 Das3.3 Rechnen mit Gleichungen3.2.5 undnitionen disjunkte Muster Ausdrücke 3.3.1 Variablen, Funktionsanwendungen und Konstruktoren3.3.2 Fallunterscheidungen 3.3.3 Funktionsausdrücke 3.3.4 Lokale Definitionen 3.4 Anwendung: Binärbäume 3.5 Vertiefung: Rechnen in Haskell 3.5.1 Eine Kernsprache/Syntaktischer Zucker 3.5.2 Auswertung von 3.5.4 Fallunterscheidungen 3.5.3 Auswertung von Funktionsanwendungen Auswertung von lokalen Defi nitionen 3 Eine einfache Programmiersprache 3.1 Datentypen 3.1.1 Datentypdefi nitionen3.1.2 Typsynonyme 3.1.3 Typdeklarationen, Typprüfung und3.2.1 Typinferenz 3.1.4 Typklassen und Typkontexte 3.2 Wertdefi nitionen Musterund Funktionsbindungen 3.2.2 Bewachte Gleichungen 3.2.3 Gleichungen mit lokalen Defi nitionen 3.2.4 Das Rechnen mit Gleichungen3.2.5 Vollständige und disjunkte Muster 3.3 AusdrückeFallunterscheidungen 3.3.1 Variablen, Funktionsanwendungen und Konstruktoren3.3.2 3.3.3 Funktionsausdrücke 3.3.4 Lokale Defi nitionen 3.4 Anwendung: Binärbäume 3.5 Vertiefung: Rechnen in Haskell 3.5.1 Eine Kernsprache/Syntaktischer Zucker 3.5.2 Auswertung von Fallunterscheidungen 3.5.3 Auswertung von 3 Funktionsanwendungen 3.5.4 Auswertung von lokalen Defi nitionen Eine einfache Programmiersprache 3.1 Datentypen 3.1.1 Datentypdefi nitio nen3.1.2 Typsynonyme 3.1.3 Typdeklarationen, Typprüfung und Typinferenz 3.1.4 Typklassen und Typkontexte 3.2 Wertdefi nitionen 3.2.1 Muster- und Funktionsbindungen 3.2.2 Bewachte Gleichungen 3.2.3 Gleichungen mit lokalen Defi nitionen 3.2.4 Das Rechnen mit Gleichungen3.2.5 Vollständige und disjunkte Muster 3.3 Ausdrücke 3.3.1 Variablen, Funktionsanwendungen und Konstruktoren3.3.2 Fallunterscheidungen 3.3.3 Funktionsausdrücke 3.3.4 Lokale Defi nitionen 3.4 Anwendung: Binärbäume 3.5 Vertiefung: Rechnen in Haskell 3.5.1 Eine Kernsprache/ Syntaktischer Zucker 3.5.2 Auswertung von Fallunterscheidungen 3.5.3 Auswertung von Funktionsanwendungen 3.5.4 Auswertung von lokalen Defi nitionen 3 Eine einfache Programmiersprache 3.1 Datentypen 3.1.1 Datentypdefi nitionen3.1.2 Typsynonyme 3.1.3 Typdeklarationen, Typprüfung und Typinferenz 3.1.4 Typklassen und Typkontexte 3.2 Wertdefi nitionen 3.2.1 Musterund Funktionsbindungen 3.2.2 Bewachte Gleichungen 3.2.3 Gleichungen mit lokalen Defi nitionen 3.2.4 Das Rechnen mit Gleichungen3.2.5 Vollständige und disjunkte Muster 3.3 Ausdrücke 3.3.1 Variablen, Funktionsanwendungen und Konstruktoren3.3.2 Fallunterscheidungen 3.3.3 Funktionsausdrücke 3.3.4 in Lokale Definitionen 3.4 Anwendung: Binärbäume 3.5 Vertiefung: Rechnen Haskell 3.5.1 Eine Kernsprache/Syntaktischer Zucker 3.5.2 Auswertung von 3.5.4 Fallunterscheidungen 3.5.3 Auswertung von Funktionsanwendungen Auswertung von lokalen Definitionen 3 Eine einfache Programmiersprache 3.1 Datentypen 3.1.1 Datentypdefi nitionen3.1.2 Typsynonyme 3.1.3 Typdeklarationen, Typprüfung und Typinferenz 3.1.4 Typklassen und Algorithmen und Datenstrukturen Typkontexte 3.2 Wertdefi nitionen 3.2.1 Musterund Funktionsbindungen 3.2.2 Bewachte Gleichungen 3.2.3 Gleichungen mit lokalen DefiInitionen 3.2.4 Das Rechnen mit Gleichungen3.2.5 Vollständige und disjunkte Prof. Dr. Funktionsanwendungen Robert Giegerich · Universität Muster 3.3 AusdrückeFallunterscheidungen 3.3.1 Variablen, und Bielefeld · WS 2004/2005 Konstruktoren3.3.2 3.3.3 Funktionsausdrücke 3.3.4 Lokale Definitionen 3.4 Anwendung: Binärbäume 3.5 Vertiefung: Rechnen in Haskell 3.5.1 Eine Kernsprache/Syntaktischer Zucker 3.5.2 Auswertung von Fallunterscheidungen 3.5.3 Auswertung von 3 Funktionsanwendungen 3.5.4 Auswertung von lokalen Defi nitionen Eine einfache Programmiersprache 3.1 Datentypen 3.1.1 Datentypdefi nitio nen3.1.2 Typsynonyme 3.1.3 Typdeklarationen, Typprüfung und Typinferenz 3.1.4 Typklassen und Typkontexte 3.2 Wertdefi nitionen 3.2.1 Musterund Funktionsbindungen 3.2.2 Bewachte Gleichungen 3.2.3 Gleichungen mit lokalen Defi nitionen 3.2.4 Das 3.3 Rechnen mit Gleichungen3.2.5 Vollständige und disjunkte Muster Ausdrücke 3.3.1 Variablen, Funktionsanwendungen und Konstruktoren3.3.2 Fallunterscheidungen 3.3.3 Funktionsausdrücke 3.3.4 Lokale Defi nitionen Anwendung: Binärbäume 3.5 Vertiefung: Rechnen in von Haskell 3.5.13.4 Eine Kernsprache/ Syntaktischer Zucker 3.5.2 Auswertung Fallunterscheidungen 3.5.3 Auswertung von Funktionsanwendungen 3.5.4 Auswertung von lokalen Defi nitionen Eine einfache Programmiersprache 3.1 DatentypenTypprüfung 3.1.1 Datentypdefi nitionen3.1.2 Typsynonyme 3.1.3 Typdeklarationen, und Typinferenz 3.1.4 Typklassen und Typkontexte 3.2 Wertdefi nitionen 3.2.1 Musterund Funktionsbindungen 3.2.2 Bewachte Gleichungen 3.2.3 Gleichungen mit lokalen Defi nitionen 3.2.4 Das Rechnen mit Gleichungen3.2.5 Vollständige und disjunkte Muster 3.3 Ausdrücke 3.3.1 Variablen, Funktionsanwendungen und Konstruktoren3.3.2 Kapitel 3: Eine einfache Programmiersprache Algorithmen und Datenstrukturen I 1 Datentypen, Datentypdefinitionen data Instrument = | | | Oboe HonkyTonkPiano Cello VoiceAahs data Musik Note Ton Dauer Pause Dauer Musik :*: Musik Musik :+: Musik Instr Instrument Musik Tempo GanzeZahl Musik Algorithmen und Datenstrukturen I = | | | | | 2 Allgemeine Form data T a1 . . . am Algorithmen und Datenstrukturen I = C1 t11 . . . t1n1 | ... | Cr tr1 . . . trnr 3 Wahrheitswerte data Bool = False | True Algorithmen und Datenstrukturen I -- vordefiniert 4 Wahrheitswerte data Bool = False | True -- vordefiniert not :: Bool -> Bool -- vordefiniert Algorithmen und Datenstrukturen I 4 Wahrheitswerte data Bool = False | True -- vordefiniert not :: Bool -> Bool not True = False not False = True -- vordefiniert Algorithmen und Datenstrukturen I 4 Wahrheitswerte data Bool = False | True -- vordefiniert not :: Bool -> Bool not True = False not False = True -- vordefiniert (&&), (||) :: Bool -> Bool -> Bool -- vordefiniert Algorithmen und Datenstrukturen I 4 Wahrheitswerte data Bool = False | True -- vordefiniert not :: Bool -> Bool not True = False not False = True -- vordefiniert (&&), (||) :: Bool -> Bool -> Bool False && y = False True && y = y -- vordefiniert Algorithmen und Datenstrukturen I 4 Wahrheitswerte data Bool = False | True -- vordefiniert not :: Bool -> Bool not True = False not False = True -- vordefiniert (&&), False True True False -- vordefiniert (||) && y && y || y || y :: Bool -> Bool -> Bool = False = y = True = y Algorithmen und Datenstrukturen I 4 Wahrheitswerte data Bool = False | True -- vordefiniert not :: Bool -> Bool not True = False not False = True -- vordefiniert (&&), False True True False -- vordefiniert (||) && y && y || y || y :: Bool -> Bool -> Bool = False = y = True = y ifThenElse :: Bool -> a -> a -> a ifThenElse True a a’ = a ifThenElse False a a’ = a’ Mixfix-Notation: if x >= 0 then x else -x Algorithmen und Datenstrukturen I 4 Ganze Zahlen data Ganz = Zero | Succ Ganz Zero, Succ Zero, Succ (Succ Zero), . . . Eingebaute Datentypen: Int und Integer Operatoren: (+), (-), (*), div, mod, (^) Algorithmen und Datenstrukturen I 5 Tupeltypen data Pair a b = Pair a b data Triple a b c = Triple a b c Abkürzende Schreibweise: (x,y), (x,y,z) Selektorfunktionen: fst :: (a,b) -> a fst (a,b) = a -- vordefiniert snd :: (a,b) -> b snd (a,b) = b -- vordefiniert Algorithmen und Datenstrukturen I 6 Listen data List a = Empty | Front a (List a) Eingebaute Listen: [a] statt List a, [] statt Empty , (x:xs) statt Front x xs Abkürzende Schreibweise: [x,y,z] statt (x:y:z:[]) Algorithmen und Datenstrukturen I 7 Funktionen auf Listen (++) :: [a] -> [a] -> [a] [] ++ bs = bs (a:as) ++ bs = a:(as++bs) head :: [a] -> a head (a:as) = a tail :: [a] -> [a] tail (a:as) = as reverse :: [a] -> [a] reverse [] = [] reverse (a:as)= reverse as ++ [a] Algorithmen und Datenstrukturen I 8 Der Typ Maybe data Maybe a = Nothing | Just a -- vordefiniert minimum1 :: [Integer] -> Integer minimum1 [a] = a minimum1 (a:as) = min a (minimum1 as) minimum0 :: [Integer] -> Maybe Integer minimum0 [] = Nothing minimum0 (a:as) = Just (minimum1 (a:as)) Algorithmen und Datenstrukturen I 9 Zeichen und Zeichenketten data Char = ... | ’0’ | ’1’ ... | ... | ’A’ | ’B’ ... | ... | ’a’ | ’b’ ... -- Pseudo-Haskell type String = [Char] Abkürzende Schreibweise: "Marvin" statt [’M’,’a’,’r’,’v’,’i’,’n’], "" statt [] isSpace :: Char -> Bool isSpace c = c == ’ ’ || c == ’\t’ || c == ’\n’ || c == ’\r’ || c == ’\f’ || c == ’\v’ Algorithmen und Datenstrukturen I 10 Typsynonyme Schon gesehen: Ton, Dauer, DNA, Protein, String Nutzen und Gefahren: type OrdList a = [a] merge :: OrdList a -> OrdList a -> OrdList a merge xs ys = xs ++ ys Typ ok? Algorithmen und Datenstrukturen I 11 Typsynonyme Schon gesehen: Ton, Dauer, DNA, Protein, String Nutzen und Gefahren: type OrdList a = [a] merge :: OrdList a -> OrdList a -> OrdList a merge xs ys = xs ++ ys Typ ok? Ja Algorithmen und Datenstrukturen I 11 Typsynonyme Schon gesehen: Ton, Dauer, DNA, Protein, String Nutzen und Gefahren: type OrdList a = [a] merge :: OrdList a -> OrdList a -> OrdList a merge xs ys = xs ++ ys Typ ok? Ja Ergebnis geordnete Liste? Algorithmen und Datenstrukturen I 11 Typsynonyme Schon gesehen: Ton, Dauer, DNA, Protein, String Nutzen und Gefahren: type OrdList a = [a] merge :: OrdList a -> OrdList a -> OrdList a merge xs ys = xs ++ ys Typ ok? Ja Ergebnis geordnete Liste? Nein Algorithmen und Datenstrukturen I 11 Typdeklarationen, Typprüfung und Typinferenz map f [] = [] map f (a:as) = f a : map f as -- vordefiniert Beobachtungen über map Typ von map map hat zwei Argumente. c -> d -> e Das Ergebnis ist eine Liste. c -> d -> [b] Das zweite Argument ist eine Liste. c -> [a] -> [b] Das erste Argument ist eine Funktion, (f -> g) -> [a] -> [b] die Argumente vom Typ a erhält, (a -> g) -> [a] -> [b] und Elemente der Ergebnisliste vom Typ b liefert. (a -> b) -> [a] -> [b] map :: (a -> b) -> [a] -> [b] Algorithmen und Datenstrukturen I 12 Spezialisierungen map :: (a -> b) -> [a] -> [b] Spezialisierung von Anwendung von map a b map c’ [1/4, 1/8, 1/8, 1/4] Dauer Musik Musik Musik map genCode cs Codon AminoAcid map (map translate) orfs zwei Auftreten verschiedenen Typs! map (transponiere 5) [cDurTonika, cDurSkala, bruderJakob] inneres Auftreten Codon Protein äußeres Auftreten [[Codon]] [Protein] Algorithmen und Datenstrukturen I 13 Typklassen und Typkontexte • Eq enthält alle Typen, deren Elemente man auf Gleichheit testen kann, und definiert die folgenden Funktionen: (==) :: (Eq a) => a -> a -> Bool (/=) :: (Eq a) => a -> a -> Bool • Ord enthält alle Typen, deren Elemente man bezüglich einer Ordnungsrelation vergleichen kann, und definiert u.a. die folgenden Funktionen: (<), (<=), (>=), (>) :: (Ord a) => a -> a -> Bool max, min :: (Ord a) => a -> a -> a Algorithmen und Datenstrukturen I 14 • Num enthält alle numerischen Typen und definiert die grundlegenden arithmetischen Operationen. (+), (-), (*) :: (Num a) => a -> a -> a negate :: (Num a) => a -> a Die Funktion negate entspricht dem unären Minus. • Integral enthält die ganzzahligen Typen Int und Integer und definiert u.a. die folgenden Funktionen: div, mod :: (Integral a) => a -> a -> a even, odd :: (Integral a) => a -> Bool • Show enthält alle Typen, die eine externe Darstellung als Zeichenketten haben. Die Funktion show liefert diese Darstellung. show :: (Show a) => a -> String Algorithmen und Datenstrukturen I 15 minimum1 :: [Integer] -> Integer minimum1 [a] = a minimum1 (a:as) = min a (minimum1 as) minimum :: (Ord a) => [a] -> a minimum [a] = a minimum (a:as) = min a (minimum as) -- vordefiniert min a b = if a < b then a else b Algorithmen und Datenstrukturen I 16 Wertdefinitionen, Variablenbindungen theFinalAnswer :: Integer theFinalAnswer = 42 aShortList :: [Integer] aShortList = [1,2,3] helloWorld :: String helloWorld = "Hello World" Algorithmen und Datenstrukturen I 17 theFinalAnswer’ :: Integer theFinalAnswer’ = 6*7 aShortList’ aShortList’ helloWorld’ helloWorld’ :: [Integer] = reverse ([3]++[2,1]) :: String = "Hello" ++ " " ++ "World" monotonie :: Musik monotonie = c’ (1/1) :*: monotonie Algorithmen und Datenstrukturen I 18 Musterbindungen Tempo t (Instr i (m1 :+: m2 :+: m3:+: m4)) = bruderJakob Allgemein: p = e, mit p Muster, e Ausdruck Algorithmen und Datenstrukturen I 19 Funktionsbindungen length :: [a] -> Int length [] = 0 length (a:as) = 1 + length as Algorithmen und Datenstrukturen I -- vordefiniert 20 Allgemeiner Fall f p11 . . . p1n = e1 ... = ... f pk1 . . . pkn = ek pij : Muster, ei : Ausdrücke Algorithmen und Datenstrukturen I 21 Bewachte Gleichungen dropSpaces :: String -> String dropSpaces [] = [] dropSpaces (c:cs) | isSpace c = dropSpaces cs | otherwise = c : dropSpaces cs squeeze :: String -> String squeeze [] = [] squeeze (c:c’:cs) | isSpace c && isSpace c’ = squeeze (c’:cs) squeeze (c:cs) = c : squeeze cs Algorithmen und Datenstrukturen I 22 member :: (Ord a) member a [] = member a (b:bs) | a < b = | a == b = | a > b = Algorithmen und Datenstrukturen I => a -> OrdList a -> Bool False False True member a bs 23 Gleichungen mit lokalen Definitionen power :: (Num a, Integral b) => a -> b -> a power x n | n == 0 = 1 | n ‘mod‘ 2 == 0 = y | otherwise = y*x where y = power (x*x) (n ‘div‘ 2) Algorithmen und Datenstrukturen I 24 Gleichungen mit lokalen Definitionen power :: (Num a, Integral b) => a -> b -> a power x n | n == 0 = 1 | n ‘mod‘ 2 == 0 = y | otherwise = y*x where y = power (x*x) (n ‘div‘ 2) pow :: (Num a) => a -> Integer -> a pow x n | n == 0 = 1 | otherwise = x * pow x (n-1) Algorithmen und Datenstrukturen I 24 Gleichungen mit lokalen Definitionen power :: (Num a, Integral b) => a -> b -> a power x n | n == 0 = 1 | n ‘mod‘ 2 == 0 = y | otherwise = y*x where y = power (x*x) (n ‘div‘ 2) pow :: (Num a) => a -> Integer -> a pow x n | n == 0 = 1 | otherwise = x * pow x (n-1) xn = x2(n div 2)+n mod 2 = (x2 )n div 2 xn mod 2 Algorithmen und Datenstrukturen I 24 Lokale Musterbindung splitWord :: String -> (String, String) splitWord [] = ([],[]) splitWord (c:cs) | isSpace c = ([], c:cs) | otherwise = (c:w, cs’) where (w,cs’) = splitWord cs Algorithmen und Datenstrukturen I 25 Gültigkeits- oder Sichtbarkeitsbereiche f :: Int -> Int f x = f (x+x) where x = 1 f x = x Algorithmen und Datenstrukturen I -- Negativ-Beispiel 26 Gültigkeits- oder Sichtbarkeitsbereiche f :: Int -> Int f x = f (x+x) where x = 1 f x = x -- Negativ-Beispiel f1 :: Int -> Int f1 x1 = f2 (x2+x2) where x2 = 1 f2 x3 = x3 Algorithmen und Datenstrukturen I 26 Abseitsregel • Das erste Zeichen der Definition unmittelbar nach dem where bestimmt die Einrücktiefe des neu eröffneten Definitionsblocks. • Zeilen, die weiter als bis zu dieser Position eingerückt sind, gelten als Fortsetzungen einer begonnenen lokalen Definition. • Zeilen auf gleicher Einrücktiefe beginnen eine neue Definition im lokalen Block. • Die erste geringer eingerückte Zeile beendet den lokalen Block. Algorithmen und Datenstrukturen I 27 Die allgemeine Form von Gleichungen f p11 . . . p1n m1 pk1 . . . pkn mk ... f Die pij sind beliebige Muster und die mi nehmen wahlweise eine der beiden folgenden Formen an: = e where { d1 ; . . . ;dp } oder | g1 = e1 ... | gq = eq where { d1 ; . . . ;dp } Algorithmen und Datenstrukturen I 28 Das Rechnen mit Gleichungen q :: (Num a) => a -> a q x = 3*x^2 + 1 q 2 - 10 (Definition von q) ⇒ (3 * 2^2 + 1) - 10 ⇒ (3 * 4 + 1) - 10 (Definition von (^)) ⇒ (12 + 1) - 10 (Definition von (*)) ⇒ 13 - 10 (Definition von (+)) ⇒ 3 (Definition von (-)) Paßt f p1 . . . pn | g = e auf Anwendung f a1 . . . an ? Algorithmen und Datenstrukturen I 29 Vollständige und disjunkte Muster unique [] = [] unique [a] = [a] unique (a:(b:z)) = if a == b then unique (b:z) else a : unique (b:z) head :: [a] -> a -- vordefiniert head [] = error "head of empty list" head (a:x) = a Algorithmen und Datenstrukturen I 30 head’ :: [Integer] -> Maybe Integer head’ [] = Nothing head’ (a:x) = Just a head :: [a] -> a -- vordefiniert head’’’ :: [a] -> Maybe a head’’’ [] = Nothing head’’’ (a:x) = Just a Algorithmen und Datenstrukturen I 31 words :: String -> [String] words xs = wds [] xs ws :: String -> wds "" "" wds ws "" wds "" (’ ’:xs) wds "" ( x :xs) wds ws (’ ’:xs) wds ws ( x :xs) Algorithmen und Datenstrukturen I String -> [String] = [] = [reverse ws] = wds "" xs = wds [x] xs = (reverse ws) : wds "" xs = wds (x:ws) xs 32 Bindungsstärken und Assoziativitäten Bindungsstärke 9 8 7 6 5 4 4 3 2 1 0 Algorithmen und Datenstrukturen I linksassoziativ !! nicht assoziativ rechtsassoziativ . ^, ^^, ** \\ ==, /=, <, <=, >, >=, ‘elem‘, ‘notElem‘ :, ++ *, /, ‘div‘, ‘mod‘, ‘rem‘, ‘quot‘ +, - && || >>, >>= $, ‘seq‘ 33 Fallunterscheidungen length :: [a] -> Int length [] = 0 length (a:as) = 1 + length as -- vordefiniert length’ :: [a] -> Int length’ as = case as of [] -> 0 a:as’ -> 1 + length’ as’ last’ :: [a] -> a last’ as = case reverse as of a:as’ -> a Algorithmen und Datenstrukturen I 34 Allgemeine Form von Fallunterscheidungen case e of { p1 m1 ; . . . ;pn mn } Die pi sind beliebige Muster und die mi nehmen wahlweise eine der beiden folgenden Formen an: -> e where { d1 ; . . . ;dp } oder | g1 -> e1 ... | gq -> eq where { d1 ; . . . ;dp } Algorithmen und Datenstrukturen I 35 words :: String -> [String] -- vordefiniert words cs = case dropSpaces cs of [] -> [] cs’ -> w : words cs’’ where (w,cs’’) = splitWord cs’ minimum0’ :: (Ord a) => [a] -> Maybe minimum0’ [] = Nothing minimum0’ (a:as) = case minimum0’ as Nothing -> Just Just m -> Just Algorithmen und Datenstrukturen I a of a (min a m) 36 Funktionsausdrücke Ist n + 1 ein Wert oder eine Funktion? Als Funktion: f n = n + 1 \n -> n + 1 Allgemeine Form eines Funktionsausdrucks: \p1 . . . pn -> e . \p1 p2 -> e als Abkürzung für \p1 -> \p2 -> e Algorithmen und Datenstrukturen I 37 Gestaffelte Funktionen add :: Integer -> Integer -> Integer add m n = m + n add’ :: Integer -> (Integer -> Integer) add’ = \m -> \n -> m + n Algorithmen und Datenstrukturen I 38 Gestaffelte Funktionen add :: Integer -> Integer -> Integer add m n = m + n add’ :: Integer -> (Integer -> Integer) add’ = \m -> \n -> m + n add0 :: (Integer,Integer) -> Integer add0 (m,n) = m + n dup :: a -> (a,a) dup a = (a,a) double :: Integer -> Integer double n = add0 (dup n) Algorithmen und Datenstrukturen I 38 note :: Int -> Int -> Dauer -> Musik note oct h d = Note (12 * oct + h) d note Eine Note in einer beliebigen Oktave und von beliebiger Höhe und Dauer. note 2 Eine Note in der dritten Oktave und von beliebiger Höhe und Dauer. note 2 ef Die Note f in der dritten Oktave und von beliebiger Dauer. note 2 ef (1/4) ergibt Note 29 (1/4). Algorithmen und Datenstrukturen I 39 Lokale Definitionen mit let power’ :: (Integral b, Num a) => a -> b -> a power’ x n = if n == 0 then 1 else let y = power’ (x*x) (n ‘div‘ 2) in if n ‘mod‘ 2 == 0 then y else y*x Allgemein: let {e1 ; . . . ; en } in e . Algorithmen und Datenstrukturen I 40 Binärbäume 3 1 1 2 2 Algorithmen und Datenstrukturen I 3 4 41 Binärbäume 3 1 1 2 2 data Tree a = Nil | Leaf a | Br (Tree a) (Tree a) Algorithmen und Datenstrukturen I 3 4 deriving Show 41 3 1 t1, t2 :: Tree Integer 2 t1 = Br (Br (Leaf 1) (Leaf 2)) (Leaf 3) 1 t2 = Br (Br (Leaf 1) Nil) (Br (Br (Leaf 2) (Leaf 3)) (Br Nil (Leaf 4))) 2 Algorithmen und Datenstrukturen I 3 4 42 leaves leaves leaves leaves :: Tree a -> [a] Nil = [] (Leaf a) = [a] (Br l r) = leaves l ++ leaves r leftist :: [a] -> Tree a leftist [] = Nil leftist (a:as) = Br (leftist as) (Leaf a) Algorithmen und Datenstrukturen I 43 leaves’ leaves’ leaves’ leaves’ leaves’ :: Tree a -> [a] Nil = (Leaf a) = (Br Nil r) = (Br (Leaf a) r) = Algorithmen und Datenstrukturen I [] [a] leaves’ r a : leaves’ r 44 leaves’ leaves’ leaves’ leaves’ leaves’ :: Tree a -> [a] Nil = (Leaf a) = (Br Nil r) = (Br (Leaf a) r) = [] [a] leaves’ r a : leaves’ r leaves’ (Br (Br l’ r’) r) = leaves’ (Br l’ (Br r’ r)) v t Algorithmen und Datenstrukturen I u =⇒ t u v 44 leaves’ leaves’ leaves’ leaves’ leaves’ leaves’ :: Tree a -> [a] Nil (Leaf a) (Br Nil r) (Br (Leaf a) r) (Br (Br l’ r’) r) = = = = = [] [a] leaves’ r a : leaves’ r leaves’ (Br l’ (Br r’ r)) leaves’ (Br (Br (Leaf 1) (Leaf 2)) (Leaf 3)) ⇒ leaves’ (Br (Leaf 1) (Br (Leaf 2) (Leaf 3))) (Def. leaves’.5) ⇒ 1 : leaves’ (Br (Leaf 2) (Leaf 3)) (Def. leaves’.4) ⇒ 1 : 2 : leaves’ (Leaf 3) (Def. leaves’.4) ⇒ 1 : 2 : [3] (Def. leaves’.2) Algorithmen und Datenstrukturen I 45 build :: [a] -> Tree a build [] = Nil build [a] = Leaf a build as = Br (build (take k as)) (build (drop k as)) where k = length as ‘div‘ 2 take :: Int -> [a] -> [a] take n (a:as) | n > 0 = a:take (n-1) as take _ _ = [] Algorithmen und Datenstrukturen I 46 build [1..11]: 1 2 3 6 4 5 9 7 8 10 11 11 = 5+6 = (2 + 3) + (3 + 3) = ((1 + 1) + (1 + 2)) + ((1 + 2) + (1 + 2)) = ((1 + 1) + (1 + (1 + 1))) + ((1 + (1 + 1)) + (1 + (1 + 1))) . Algorithmen und Datenstrukturen I 47 build’ :: [a] -> Tree a build’ as = fst (buildSplit (length as) as) buildSplit :: Int -> [a] -> (Tree a, [a]) buildSplit 0 as = (Nil, as) buildSplit 1 as = (Leaf (head as), tail as) buildSplit n as = (Br l r, as’’) where k = n ‘div‘ 2 (l,as’) = buildSplit k as (r,as’’) = buildSplit (n-k) as’ Algorithmen und Datenstrukturen I 48 Syntaktischer Zucker / Kernsprache • Mustergleichungen / case-Ausdrücke length [] = 0 length (x:xs) = 1 + length xs length’ xs = case xs of [] -> 0 (x:xs) -> 1 + length’ xs • Funktionsdefinitionen / Funktions-Ausdrücke add m n = m + n add’ = \m -> \n -> m + n Algorithmen und Datenstrukturen I 49 • where-Klauseln / let-Ausdrücke double n = add0 (dup n) where dup a = (a,a) double n = let dup a = (a,a) in add0 (dup n) Algorithmen und Datenstrukturen I 50 Auswertung von Fallunterscheidungen case C e1 ...ek of {...; C x1 ...xk -> e;...} (case-Regel) ⇒ e[x1 /e1 , . . . , xn /en ] Algorithmen und Datenstrukturen I 51 abs :: (Ord a, Num a) => a -> a abs n = case n >= 0 of True -> n False -> -n encode :: (Num a) => Maybe a -> a encode x = case x of Nothing -> -1 Just n -> abs n encode (Just 5) ⇒ case Just 5 of {Nothing -> -1; Just n -> abs n} (Def. encode) ⇒ abs 5 (case − Regel) ⇒ case 5 >= 0 of {True -> 5; False -> -5} (Def. abs) ⇒ case True of {True -> 5; False -> -5} (Def. >=) ⇒ 5 Algorithmen und Datenstrukturen I (case − Regel) 52 Auswertung von Funktionsanwendungen (\x -> e) a ⇒ e[x/a] Algorithmen und Datenstrukturen I (β-Regel) (1) 53 abs = encode = \n -> case n >= 0 of {True -> n; False -> -n} \x -> case x of {Nothing -> -1; Just n -> abs n} encode (Just 5) (Def. encode) ⇒ (\x-> case x of {Nothing-> -1; Just n-> abs n}) (Just 5) ⇒ case Just 5 of {Nothing -> -1; Just n -> abs n} ⇒ abs 5 ⇒ (\n -> case n >= 0 of {True -> n; False -> -n}) 5 (Def. abs) ⇒ case 5 >= 0 of {True -> 5; False -> -5} (β − Regel) ⇒ case True of {True -> 5; False -> -5} (Def. (>=)) ⇒ 5 Algorithmen und Datenstrukturen I (β − Regel) (case − Regel) (case − Regel) 54 Auswertung von lokalen Definitionen let {x1 = e1 ;...;xn = en } in e ⇒ e[x1 /let {x1 = e1 ;...;xn = en } in e1 , . . . , (let-Regel) xn /let {x1 = e1 ;...;xn = en } in en ] Algorithmen und Datenstrukturen I 55 rep n a = let x = a:x in take n x rep 2 8 ⇒ let x = 8:x in take 2 x ⇒ take 2 (let x = 8:x in 8:x) (let − Regel) ⇒ take 2 (8:let x = 8:x in 8:x) (let − Regel) ⇒ 8:take 1 (let x = 8:x in 8:x) (Def. take) ⇒ 8:take 1 (8:let x = 8:x in 8:x) (let − Regel) ⇒ 8:8:take 0 (let x = 8:x in 8:x) (Def. take) ⇒ 8:8:[] (Def. take) Algorithmen und Datenstrukturen I (Def. rep) 56