Listen und Funktionen auf Listen Achtung Zunächst: Einfache Einführung von Listen Listenfunktionen zugehörige Auswertung Genauere Erklärungen zu Listenfunktionen folgen noch (in ca, 1-2 Wochen) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 1
Listen und Listenfunktionen Listen modellieren Folgen von gleichartigen, gleichgetypten Objekten. [0,1,2,3,4,5,6,7,8,9] Typ: [Integer]; d.h. Liste von Integer. [] leere Liste, (Nil) [ a, b, c ] Typ: [Char]; abgekürzt als String Druckbild: "abc" [[], [0], [1, 2]] Liste von Listen; Typ [[Integer]], d.h. eine Liste von Listen von Integer-Objekten. [1..] potentiell unendliche Liste [1,2,3,...] P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 2
Listen und Listenfunktionen zwei Schreibweisen für Listen: [0, 1, 2] (0 : (1 : (2 : []))) schöne Darstellung interne Darstellung mit Druckbild einer Liste zweistelligem Infix-Listen-Konstruktor : und dem Konstruktor [] Eingebaute, listenerzeugende Funktionen: [n..] erzeugt die Liste der Zahlen ab n. [n..m] erzeugt die Liste von n bis m [1..10] ergibt [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [n,m..k] erzeugt die Liste von n bis k mit Schritten m n P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 3
Darstellung von Listen Listen sind aufgebaut mittels zwei Konstruktoren: [] Konstante für die leere Liste : Zweistelliger Infix-Konstruktor Linkes Argument: erstes Element der Liste Rechtes Argument: Restliste Beispiel für Haskells Listenerzeugung: 8:[] Liste [8] mit dem Element 8 9:(8:[]) Liste [9.8] mit zwei Elementen 8,9 10:(9:(8:[])) Liste [10,9,8] mit drei Elementen P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 4
Baum-Bild einer Liste 10 : 9 : 8 [] : P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 5
Einfache Listenfunktionen Definitionen head (x:xs) = x --Erstes Element tail (x:xs) = xs --Restliste Auswertungen Prelude> head [] *** Exception: Prelude.head: empty list Prelude> head [1] ##intern: (1 : []) 1 Prelude> tail [] *** Exception: Prelude.tail: empty list Prelude> tail [1] [] Prelude> P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 6
Funktionen auf Listen: lengthr Länge einer Liste: lengthr [] = 0 lengthr (x:xs) = 1 + (lengthr xs) [] und (x:xs) in der Position von formalen Parametern nennt man Muster(Pattern) Zwei Fälle in den Definitionen: 1. Leere Liste oder 2. nicht-leere Liste. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 7
Beispiel lengthr lengthr [] = 0 lengthr (x:xs) = 1 + (lengthr xs) Auswertung lengthr (10:(9:(8:[]))) Zweiter Fall; [10/x,(9:(8:[]))/xs] 1+ (lengthr (9:(8:[]))) Zweiter Fall; [9/x, (8:[])/xs] 1+(1+ (lengthr (8:[]))) Zweiter Fall; [8/x, ([])/xs] 1+(1+ (1+ (lengthr []))) Erster Fall; 1+(1+ (1+ (0))) 3 Addition 3 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 8
Funktionen auf Listen: map map f [] = [] map f (x:xs) = (f x) : (map f xs) map wendet eine Funktion f auf alle Elemente einer Liste an konstruiert Liste der Ergebnisse. [] und (x:xs) links sind Muster(Pattern) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 9
Funktionen auf Listen: Beispiele map f [] = [] map f (x:xs) = (f x) : (map f xs) map quadrat (1:(2:[])) Zweite Gleichung [quadrat/f,1/x,(2:[])/xs] quadrat 1 : map quadrat (2:[]) Interpreter will alles auswerten: deshalb 1*1 : map quadrat (2:[]) 1 : map quadrat (2:[]) Zweite Gleichung 1 : (quadrat 2 : map quadrat []) wg Interpreter 1 : (2*2 : map quadrat []) 1 : (4 : map quadrat []) Erste Gleichung 1 : (4 : []) = [1,4] P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 10
Listenerzeugende Funktionen [n..] erzeugt die Liste der Zahlen ab n. [n..m] erzeugt die Liste von n bis m [1..10] ergibt [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [n,m..k] erzeugt die Liste von n bis k mit Schritten m n P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 11
Listenerzeugende Funktionen: Beispiel [n..m] fromto n m = if n <= m then n : (fromto (n+1) m) else [] [1..10] Benutze fromto fromto 1 10 Definitionseinsetzung if 1 <= 10 then... if True then... 1: (fromto (1+1) 10) wg. Eingabe in den Interpreter 1: (if (1+1) <= 10 then... ) 1: (if 2 <= 10 then... ) 1: (if True then... ) 1: (2:(fromTo (2+1) 10) )... 1:(2:(3:...(10:[] )... )) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 12
istleer [] = True istleer (x:xs) = False Auswertung: Wieviel ist nötig? zahlenab n = n: zahlenab (n+1) Auswertung istleer [1..] istleer (zahlenab 1) istleer (1: zahlenab (1+1)) False verwende zahlenab Zweite Gleichung von istleer P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 13
Listenfunktionen und Listenerzeuger *Main> map quadrat [1..10] [1,4,9,16,25,36,49,64,81,100] *Main> map quadrat [1..] [1,4,9,16,25,36,49,64,81,100,121,... Der Listenerzeuger [1..] erzeugt soviel von der Liste [1,2,3,4,5, usw. wie von der Listenfunktion benötigt wird. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 14
Beispiel map quadrat [1..] verwende zahlenab map quadrat (zahlenab 1) Auswertung zahlenab 1 map quadrat (1:zahlenAb (1+1)) Muster in map passt quadrat 1 : map quadrat (zahlenab (1+1)) wg. Interpreter 1*1 : map quadrat (zahlenab (1+1)) 1 : map quadrat (zahlenab (1+1)) 1 : map quadrat ((1+1): zahlenab ((1+1)+1)) 1 : (quadrat (1+1) : map zahlenab ((1+1)+1)) verzögerte Red. 1 : (quadrat 2 : map zahlenab (2+1)) 1 : (2*2 : map zahlenab (2+1)) 1 : (4 : map zahlenab (2+1))... P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 15
Listenfunktion append Die folgende Funktion hängt zwei Listen zusammen: append [] ys append (x:xs) ys = ys = x : (append xs ys) In Haskell: ++ und Infix P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 16
Beispiele Main> [] ++ [3,4,5] [3,4,5] Main> [0,1,2] ++ [] [0,1,2] Main> [0,1,2] ++ [3,4,5] [0,1,2,3,4,5] Main> [0..10000] ++ [10001..20000] == [0..20000] True P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 17
Funktionen auf Listen (2) Filtern von Elementen aus einer Liste: filter f [] = [] filter f (x:xs) = if (f x) then x : filter f xs else filter f xs Die ersten n Elemente der Liste xs: take 0 _ = [] take n [] = [] take n (x:xs) = x : (take (n-1) xs) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 18
Auswertungsreihenfolge, Definitionseinsetzung Auswertung von f s 1... s n wenn Muster verwendet wurden: Vor Definitionseinsetzung diejenigen Argumente auswerten, die für die Fallunterscheidung benötigt werden. Aber nur soviel wie nötig Zuordnung: Mustervariablen zu Ausdruck analog wie Zuordnung: formale Parameter zu Argumenten. Z.B. Muster (x:xs) und Argument (s:t) ergibt [s/x, t/xs] P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 19
Beispiele zu take repeat x = x : repeat x Auswertung: take 10 (repeat 1) take 10 (1:repeat 1) 1:(take (10-1) (repeat 1)) -- (x:xs) = (1:(repeat 1)) 1:(take 9 (repeat 1)) 1:(take 9 (1:(repeat 1))) 1:(1:(take (9-1) (repeat 1))... 1:(1:... 1:(take (1-1) (repeat 1)) 1:(1:... 1:(take 0 (repeat 1)) -- n = 0 1:(1:... 1:[]) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 20
Beispiele zu filter und take filter (< 5) [1..10] [1,2,3,4] *Main> let ptest x = ist_primzahl_ft_naiv x && (not (primzahlq x)) *Main> filter ptest [2..] [561,1105,1729,2465,2821,6601 *Main> take 10 [20..40] [20,21,22,23,24,25,26,27,28,29] *Main> take 10 [20,23..] [20,23,26,29,32,35,38,41,44,47] P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 21
Iterative Prozesse mit Listenargumenten Bei Verwendung von Listenargumenten: Die folgenden Begriffe sind unverändert: linear rekursiv, end-rekursiv, Baum-rekursiv verschachtelt Baum-rekursiv iterativ muss neu definiert werden. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 22
Iterativer Auswertungsprozess zu f Ein iterativer Auswertungsprozess liegt vor, wenn (f a 1... a n ) (f a 1... a n ) (f a(2) 1... a(2) n ) (f a (3) 1... a(3) n )...... (f a (m) 1... a (m) n )... und alle a (j) i sind Basiswerte oder komplett ausgewertete, endliche Listen P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 23
iterative Version f iter von f f iter ist iterative Version von f Wenn: f und f iter das gleiche berechnen und f iter einen iterativen Prozess erzeugt für alle Basiswerte und alle komplett ausgewerteten endlichen Listen als Eingaben P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 24
Applikativ, Strikt Listenargumente nennt man: einfach ausgewertet: wenn Listen-Fallunterscheidung möglich ist, d.h. [] oder : ist Top-Konstruktor des Arguments Funktion ist applikativ: wenn sie zuerst ihre Argumente auswertet. Funktion ist strikt: wenn sie ihre Argumente (irgendwann) auswertet. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 25
Beispiel: iterative Version von lengthr: length_lin xs = length_linr 0 xs length_linr s [] = s length_linr s (x:xs) = (length_linr_app (s+1) xs)) length_linr_app s xs = strikt_1 s (length_linr s xs) lengthr [] = 0 lengthr (x:xs) = 1 + lengthr xs P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 26
Beispiel: iterativer Prozess Beachte: length linr ist applikativ length_lin (9:(8:(7:(6:...(1:[]))))) length_linr 0 (9:(8:(7:(6:...(1:[]))))) length_linr 1 (8:(7:(6:...(1:[])))) length_linr 2 (7:(6:...(1:[]))) length_linr 3 (6:...(1:[]))... P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 27
Allgemeine Funktionen auf Listen Allgemeine Funktionen (Methoden): foldl und foldr Die Argumente sind: eine zweistellige Operation, ein Anfangselement (Einheitselement) und die Liste. foldl e [a 1,..., a n ] entspricht ((... ((e a 1 ) a 2 )... ) a n ). foldr e [a 1,..., a n ] entspricht a 1 (a 2 (... (a n e))) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 28
Fold-Verwendungen Summe bzw. Produkt einer Liste von Zahlen: sum xs = foldl (+) 0 xs produkt xs = foldl (*) 1 xs concat xs = foldr (++) [] xs foldl (+) 0 [1,2,3,4] entspricht ((((0+1)+2)+3)+4) foldr (++) [] [[0],[2,3],[5]] entspricht [0] ++ ([2,3] ++ ([5] ++ [])) Mal ist foldl, mal foldr besser geeignet. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 29
Lokale Funktionsdefinitionen, anonyme Funktion, Lambda-Ausdrücke Statt Funktion mit Namen auf der Programmebene: Lambda-Ausdruck \x 1... x n -> Ausdruck Die Notation \x -> ist Ersatz für die Church-Notation: λx. Beispiel äquivalente Definition von quadrat. quadrat = \x -> x*x Lokale Funktionsdefinition: Anonyme Funktion Lambda-Ausdruck an der Stelle von f Lambda-Ausdruck hat keine Namen Äquivalent sind: \x1 -> (\x2 ->... (\xn -> t)...) und \x1 x2... xn -> t. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 30
let {x 1 = s 1 ;... ; x n = s n } in t let und lokale Bindungen {x 1 = s 1 ;... ; x n = s n } ist eine lokale Umgebung die Variablen x i können in t vorkommen mit der Bedeutung: Wert von s i t der eigentliche Ausdruck In Haskell: rekursives let. D.h. x i kann in jedem s j vorkommen Beachte im ghci-interpreter: Spezielle Verwendung des let P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 31
Beispiel let-reduktion let fakt = \x -> if x <= 1 then 1 else x*(fakt (x-1)) in fakt Auswertung der Anwendung von fakt auf 5 ergibt: (Die Reduktionsregeln kommen später nochmal) (Hier etwas vereinfacht) (let fakt = \x -> if x <= 1 then 1 else x*(fakt (x-1)) in fakt) 5 -> let fakt =... in (fakt 5) -> let fakt =... in if 5 <= 1 then 1 else 5*(fakt (5-1)) -> let fakt =... in if False then 1 else 5*(fakt (5-1)) -> let fakt =... in 5*(fakt (5-1))... ergibt: 120. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 32
Erweiterungen des let Funktionen sind definierbar direkt in einem rekursiven let: let {f x 1... x n = s;...} in t ist das gleiche wie: let {f = \x 1... x n -> s;...} in t (let fakt = \x -> if x <= 1 then 1 else x*(fakt (x-1)) in fakt ist äquivalent zu (let fakt x = if x <= 1 then 1 else x*(fakt (x-1)) in fakt P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 33
Freie und Gebundene Variablen, Gültigkeitsbereiche Um Definitionen von lokalen Namen korrekt zu handhaben braucht man neue Begriffe: Gültigkeitsbereich einer Variablen x freie Variablen eines Ausdrucks gebundene Variablen eines Ausdrucks Text-Fragment(e) des Programms in dem dieses x gemeint ist. Variablen, deren Bedeutung außerhalb des Ausdrucks festgelegt wird. Variablen, deren Bedeutung innerhalb des Ausdrucks festgelegt wird. Problem: Variablen können mit gleichem Namen, aber verschiedener Bedeutung in einem Ausdruck vorkommen: Lösung: Exakte Festlegung der Gültigkeitsbereiche für jedes syntaktische Konstrukt Umbenennen von gebundenen Variablennamen, falls nötig P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 34
Beispiel \x-> x*x Gültigkeitsbereich von x: der Ausdruck x*x die Variable x ist gebunden von \x x*x in diesem Ausdruck ist x frei P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 35
Definition von FV FV: ergibt Menge von Variablen-Namen. F V (x) := {x}, wenn x ein Variablenname ist F V ((s t)) := F V (s) F V (t) F V (if t 1 then t 2 else t 3 ) := F V (t 1 ) F V (t 2 ) F V (t 3 ) F V (\x 1... x n -> t) := F V (t) \ {x 1,..., x n } F V (let x 1 = s 1,..., x n = s n in t) := (F V (t) F V (s 1 )... F V (s n )) \ {x 1,..., x n } F V (let f x 1... x n = s in t) := F V (let f = \x 1... x n -> s in t) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 36
Beispiel: freie Variablen F V (\x -> (f x y)) = F V (f x y ) \ {x} =... = {x, f, y} \ {x} = {f, y} P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 37
Gebundene Variablen GV (t) Entsprechend der F V -Definition: GV (x) := GV ((s t)) := GV (s) GV (t) GV (if t 1 then t 2 else t 3 ) := GV (t 1 ) GV (t 2 ) GV (t 3 ) GV (\x 1... x n -> t) := GV (t) {x 1,..., x n } GV (let x 1 = s 1,..., x n = s n in t) := (GV (t) GV (s 1 )... GV (s n ) {x 1,..., x n }}) GV (let f x 1... x n = s in t) := GV (let f = \x 1... x n -> s in t) = {f, x 1,..., x n } GV (s) GV (t) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 38
Beispiel : Berechnung von gebundenen Variablen GV(\x -> (f x y)) = GV (f x y) {x} =... = {x} = {x} P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 39
Lexikalischer Gültigkeitsbereich einer Variablen let x = s in t die Vorkommen der freien Variablen x in s, t werden gebunden. s, t ist der Gültigkeitsbereich der Variablen x \x 1... x n -> t die freien Variablen x 1,..., x n in t werden gebunden. t ist der Gültigkeitsbereich der Variablen x 1,..., x n. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 40
Beispiel Ausdruck t = \x -> (x (\x -> x*x)) x ist in t gebunden, aber in zwei Gültigkeitsbereichen (Bindungsbereichen): \x -> (x (\x -> x*x)) In (x (\x -> x*x)) kommt x frei und gebunden vor. Umbenennen des gebundenen x in y ergibt: (x (\y -> y*y)) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 41
Beispiele Zwei Gültigkeitsbereiche für x in einem let-ausdruck: let x = 10 in (let x = 100 in (x+x)) + x Umbenennung ergibt: let x1 = 10 in (let x2 = 100 in (x2+x2)) + x1 Dieser Term wertet zu 210 aus. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 42
Beispiele Der Ausdruck let x = (x*x) in (x+x) führt zu Nichtterminierung. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 43
Beispiel: Reihenfolgenunabhängigkeit der let y = 20*z x = 10+y z = 15 in x Bindungen Wertet aus zu : 310. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 44
Beispiel geschachtelte Bindungsbereiche let {x = 1;y = 2} in (let {y =3; z = 4} in (let z = 5 in (x+y+z))) x = 1; y = 2 y = 2; z = 4 z = 5 (x+y+z) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 45
Programm als let Ein Programm mit den Definitionen f i := e i i = 1,..., n und dem auszuwertenden Ausdruck main kann als großes let betrachtet werden: let {f 1 := e 1 ;... ; f n := e n } in main P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 46
Optimierung mittels let Vermeidung redundanter Auswertungen mit let f(x, y) := x(1 + xy) 2 + y(1 y) + (1 + xy)(1 y) optimierbar durch Vermeidung von Doppelauswertungen: Der zugehörige Ausdruck ist: let a b in = 1 + x*y = 1 - y x*a*a + y*b + a*b P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 47
Reduktion von let-ausdrücken Wünsche an die Transformationsregeln: operationale Semantik für Let und Lambda können verzögerte Auswertung modellieren machen implizite Gleichheitsmarkierung explizit vermeiden Doppelauswertung P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 48
Reduktion von let-ausdrücken Plan: Mehrere Reduktionsregeln für Ausdrücke mit let Vollständige Angabe aller Regeln Verallgemeinerung des Begriffs Basiswert: WHNF als Ende einer Auswertung P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 49
Auswertungsregeln bei let und Lambda Definitionseinsetzung mit let (f t 1... t n ) (let {x 1 = t 1 ;... ; x n = t n } in Rumpf f ) Bedingungen: Die Definition von f ist: f x 1... x n = Rumpf f Rumpf f ist eine Kopie von Rumpf f, in der gebundene Variablen umbenannt sind. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 50
Auswertungsregel Beta entsprechend der Definitionseinsetzung mit let: Beta-Reduktion (mit let) ((\ x 1... x n -> e) t 1... t n ) (let {x 1 = t 1 ;... ; x n = t n } in e) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 51
Beispiel (\x -> x*x) 2 let x = 2 in x*x Es fehlen noch Regeln! P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 52
Reduktion von let-ausdrücken Let-Kopier-Regel(n) let {x = s; E nv} in e[x] p let {x = s; E nv} in e[s ] p let {x = s; y = e[x] p ; E nv} in r let {x = s; y = e[s ] p ; E nv} in r Wenn s Basiswert,oder Abstraktion, oder f t 1... t n mit n < ar(f). s ist s nach Umbenennung der gebundenen Variablen. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 53
Kopieren von Konstruktorausdrücken Let-Kopier-Regel(n) let {x = c t 1... t n ; E nv} in e[x] p let {x = c x 1... x n ; x 1 = t 1 ;... ; x n = t n ; E nv} in e[c x 1... x n ] p let {x = c t 1... t n ; y = e[x] p ; E nv} in r let {x = c x 1... x n ; x 1 = t 1 ;... ; x n = t n ; y = e[c x 1... x n ] p ; E nv} in r Wenn c Konstruktor mit n = ar(c) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 54
Beispiel (\x -> x*x) 2 let x = 2 in x*x let x = 2 in 2*x let x = 2 in 2*2 let x = 2 in 4 Es fehlen immer noch Regeln! P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 55
Speicher-Bereinigung (garbage collection) Let-Speicher-Bereinigung-1 let {x 1 = s 1 ;... ; x n = s n } in e e wenn e kein freies Vorkommen der Variablen x i für i = 1,..., n hat. Let-Speicher-Bereinigung-2 let {x 1 = s 1 ;... ; x n = s n ; x n+1 = s n+1 ;...} in e let {x n+1 = s n+1 ;...} in e wenn x i für i = 1,..., n weder in e noch in einem s j mit j n + 1 frei vorkommt. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 56
Beispiel (\x -> x*x) 2 let x = 2 in x*x let x = 2 in 2*x let x = 2 in 2*2 let x = 2 in 4 4 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 57
Umbenennung von gebundenen Variablen \x 1... x n -> e \y 1... y n -> e[y 1 /x 1,..., y n /x n ] wenn y i neue Variablennamen sind. e[y 1 /x 1,..., y n /x n ]: alle freien Vorkommen von x i werden jeweils durch y i ersetzt Umbenennung aller gebundenen Variablen eines Ausdrucks: erfordert rekursives Vorgehen in allen Unterausdrücken Umbenennung geht analog für Let-Ausdrücke. Beachte, dass freie Variablen eines Ausdrucks nicht umbenannt werden. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 58
Ein komplexeres Beispiel \x -> (\y -> x ((\x -> x + y) 5)) Umbenennung: z.b. inneres x durch z ersetzen \x -> (\y -> x ((\z -> z + y) 5)). Verboten: Umbenennung von y in x. Sogenanntes Einfangen von Variablen Dies würde ergeben: \x -> (\x -> x ((\x -> x + x) 5)). Eine Variable würde dadurch ihre Zuordnung ändern P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 59
Ein komplexeres Beispiel (2) Eine korrekte Umbenennung des äußeren x ergibt: \z -> (\y -> z ((\x -> x + y) 5)). Dies kann man auch testweise in Haskell eingeben; man erhält für den falschen Ausdruck auch andere Ergebnisse. > (\x -> (\y -> x*((\x -> x+y) 5))) 2 2 14 > (\x -> (\x -> x*((\x -> x+x) 5))) 2 2 20 > (\z -> (\y -> z*((\x -> x+y) 5))) 2 2 14 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 60
Let-Verschieben Let-Anwendung-Verschieben ((let {x 1 = t 1 ;... ; x n = t n } in t) s) (let {x 1 = t 1 ;... ; x n = t n } in (t s)) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 61
Beispiel ((\x -> (\y -> x*((\z -> z+y) 5))) 2) 2 (let x = 2 in (\y -> x*((\z -> z+y) 5))) 2 (let x = 2 in ((\y -> x*((\z -> z+y) 5)) 2) (let x = 2 in (let y = 2 in x*((\z -> z+y) 5))) (let x = 2 in (let y = 2 in 2*((\z -> z+y) 5))) (let y = 2 in 2*((\z -> z+y) 5)) (let y = 2 in 2*(let z = 5 in z+y)) (let y = 2 in 2*(let z = 5 in 5+y)) (let y = 2 in 2*(5+y)) (let y = 2 in 2*(5+2)) 2*(5+2)) 2*7 14 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8th December2004) Seite 62
Let-Glätten Let-Glätten-1 (let {x 1 = t 1 ;... ; x j = (let {y 1 = r 1 ;... ; y m = r m } in t j );... ; x n = t n } in t) (let {x 1 = t 1 ;... ; x n = t n ; y 1 = r 1 ;... ; y m = r m } in t) Eine weitere Regel dazu: Let-Glätten-2 (let {x 1 = t 1 ;... ; x n = t n } in (let y 1 = r 1 ;... ; y m = r m in t)) (let {x 1 = t 1 ;... ; x n = t n ; y 1 = r 1 ;... ; y m = r m } in t) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 63
Schwache Kopfnormalform (weak head normal form, WHNF) ist eine Verallgemeinerung von Basiswert eine WHNF wird nicht weiter ausgewertet, kann aber unausgewertet Unterausdrücke enthalten schwache Kopfnormalform (WHNF): 1. Zahl oder Boolesch oder Zeichen, d.h. Basiswert 2. Lambda-Ausdruck 3. c t 1... t n und c ist ein Konstruktor und ar(c) = n 4. f t 1... t n und f ist ein Funktionsname ist mit ar(f) > n 5. (let{x 1 = s 1 ;... ; x n = s n } in t) und t ist von der Form 1 4 Zu Konstruktoren beachte: Im Moment ist nur : eingeführt und Konstanten. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 64
Normale (Verzögerte) Reihenfolge der Auswertung Die Definition ist zu umfangreich, deshalb nur Die Prinzipien und einige Regeln: nur das notwendigste wird ausgewertet Glätte äußere let-umgebung, falls notwendig Verfolge Bindungen wenn nötig und werte an Ort und Stelle aus Kopiere Ausdruck, wenn erforderlich let... in t: werte t aus Wenn WHNF erreicht wird, dann stoppe erfolgreich P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 65
Beispiel: Auswertungsstrategie Beispiel let x = (1+2) in x*x arithmetische Auswertung let x = 3 in x*x Kopieren let x = 3 in 3*x Kopieren let x = 3 in 3*3 gc 3*3 arithmetische Auswertung 9 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 66
Beispiel let-reduktion: fakt let fakt = \x -> if x <= 1 then 1 else x*(fakt (x-1)) in fakt Auswertung der Anwendung auf 5 ergibt: (let fakt= \x -> if x<=1 then 1 else x*(fakt (x-1)) in fakt) 5 let fakt=... in (fakt 5) let fakt=... in ((\y ->...) 5) let fakt=... in (let y=5 in if y<=1 then 1 else y*(fakt (y-1)) let fakt=...;y=5 in if y<=1 then 1 else y*(fakt (y-1)) let fakt=...;y=5 in if 5<=1 then 1 else y*(fakt (y-1)) let fakt=...;y=5 in if False then 1 else y*(fakt (y-1)) let fakt=...;y=5 in y*(fakt (y-1)) let fakt=...;y=5 in 5*(fakt (y-1)) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 67
Beispiel let-reduktion: fakt(2) let fakt=..;y=5 in 5*((\z->...) (y-1)) let fakt=..;y=5 in 5*(let z=(y-1) in if z<=1 then 1 else z*(fakt (z-1))) let fakt=..;y=5 in 5*(let z=(5-1) in if z<=1 then 1 else z*(fakt (z-1))) let fakt=.. in 5*(let z=(5-1) in if z<=1 then 1 else z*(fakt (z-1))) let fakt=.. in 5*(let z=4 in if z<=1 then 1 else z*(fakt (z-1))) let fakt=.. in 5*(let z=4 in if 4<=1 then 1 else z*(fakt (z-1))) let fakt=.. in 5*(let z=4 in if False then 1 else z*(fakt (z-1))) let fakt=.. in 5*(let z=4 in z*(fakt (z-1)))... let fakt=.. in 5*(4*(3*(2*1)))... let fakt=.. in 120 120 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 68
Allgemeine Methoden: Funktionen als Argumente Funktionen höherer Ordnung Beispiele für (arithmetische) Aufgabenstellungen: Nullstellenbestimmung, Integrieren, Differenzieren, Ermitteln von Maxima, Minima von Funktionen... P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 69
Nullstellenbestimmung einer stetigen Funktion mit Intervallhalbierung Sei f stetig und f(a) < 0 < f(b), m = (a + b)/2 a f (a+b)/2 b wenn f(m) > 0, dann Nullstelle in [a, m]. wenn f(m) < 0, dann Nullstelle in [m, b]. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 70
Nullstellenbestimmung: Programm (1) Parameter: f a b genau Name der arithmetischen (Haskell-) Funktion Intervall-Anfang Intervall-Ende Genauigkeit der Nullstelle (absolut) suche_nullstelle f a b genau = let fa = f a fb = f b in if fa < 0 && fb > 0 then suche_nullstelle_steigend f a b genau else if fa > 0 && fb < 0 then suche_nullstelle_fallend f a b genau else error ("Werte haben gleiches Vorzeichen" ++ (show a) ++ (show b)) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 71
Nullstellenbestimmung: Programm (2) suche_nullstelle_steigend f a b genau = suche_nullstelle_r f a b genau suche_nullstelle_fallend f a b genau = suche_nullstelle_r f b a genau suche_nullstelle_r f a b genau = let m = (mittelwert a b) in if abs (a - b) < genau then m else let fm = f m in if fm > 0 then suche_nullstelle_r f a m genau else if fm < 0 then suche_nullstelle_r f m b genau else m P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 72
Nullstellenbestimmung: Programm (3) *Main> suche_nullstelle cos 0 3 0.000000000000001 1.5707963267948966 *Main> 1.5707963267948966/pi 0.5 *Main> pi/2 1.5707963267948966 *Main> P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 73
Intervallhalbierungsmethode: Komplexität maximale Anzahl der Schritte: log 2 (L/G), wobei L Länge des Intervalls G Genauigkeit Zeitbedarf: Platzbedarf: O(log(L/G)) O(1) Unter der Annahme, dass die Implementierung der arithmetischen Funktion f O(1) Zeit und Platz braucht. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 74
Beispiel:Verwendung der Nullstellensuche n-te Wurzel aus einer Zahl a: n a nte_wurzel n a = suche_nullstelle (\x-> x^n -a) 1 (a^n) 0.00000001 *Main> nte_wurzel 10 1024 2.00000000372529 *Main> nte_wurzel 10 10 1.2589254114675787 *Main> (nte_wurzel 10 10)^10 9.999999974058156 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 75
Funktionen als Ergebnis Beispiel: Komposition von Funktionen: komp::(a -> b) -> (c -> a) -> c -> b komp f g x = f (g x) (sin komp quadrat) entspricht sin(x 2 ) und quadrat komp sin entspricht (sin(x)) 2. *Main> suche_nullstelle (sin komp quadrat) 1 4 0.00000001 1.772453852929175 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 76
Typ der Komposition Erklärung zum Typ von komp, wobei {a,b,c} Typvariablen sind Ausdruck: f 1 komp f 2 bzw. f 1. f 2 (a->b) -> (c->a) -> c->b Typ von komp (a->b) Typ von f 1 (c->a) Typ von f 2 c Typ des Arguments x der Komposition f 1. f 2 b Typ des Resultats der Komposition f 1 (f 2 x) f 1 komp f 2 :: c -> b. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 77
Beispiel: näherungsweises Differenzieren x x+ x Df(x) := f(x + dx) f(x) dx ableitung f dx = \x -> ((f(x+dx)) - (f x)) / dx Resultat: Funktion, die die Ableitung f annähert *Main> ((ableitung (\x -> x^3) 0.00001) 5) 75.00014999664018 ---- korrekter Wert: 3*5^2 = 75 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 78
Variante der Newtonschen Methode zur Bestimmung der Nullstellen y2 y1 Vorgehen: Ersetze Schätzwert y 1 durch verbesserten Schätzwert y 2 = y 1 f(y 1) Df(y 1 ) statt y 1 f(y 1) f (y 1 ) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 79
Variante der Newtonschen Methode zur Bestimmung der Nullstellen (2) newton_nst f y = if (abs (f y)) < 0.0000000001 then y else newton_nst f (newton_nst_verbessern y f) newton_nst_verbessern y f = y - (f y) / (ableitung f 0.00001 y) Beispiel: Nullstelle der Funktion x 2 x mit Startwert 4. *Main> newton_nst (\x -> x^2-x) 4 1.0000000000001112 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 80
Datentypen in Haskell Basisdatentypen Ganze Zahlen (Int) Unbeschränkte ganze Zahlen (Integer). Rationale Zahlen. Komplexe Zahlen (im Haskell-Module Complex). Gleitkommazahlen (Gleitpunktzahlen) (Float). z.b. 1.234 e-40 Zeichen, Character. i.a. ASCII-Zeichen zu 1 Byte P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 81
Standards zu Basisdatentypen IEEE-Standards zu Zahlen und Operationen Genauigkeit Rundungsalgorithmus, /-Algorithmen Fehlermeldungen: Überlauf/Unterlauf, Division durch 0 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 82
UniCode internationaler Kodierungsstandard für Zeichen. UniCode: 4 Bytes pro Zeichen Die Zeichen (fast) aller Sprachen sind berücksichtigt Unicode-Standard (www.unicode.org). drei Varianten: verschiedene Kompressionen in Haskell und in Python verfügbar P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 83
Zusammengesetzte Daten-Objekte Paar: (x, y) Beispiele (1, 2) (1, "hallo") (1,(2,"hallo")) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 84
Anwendungs-Beispiel: Rationale Zahlen Repräsentation als Paar: (Zähler, Nenner) Beachte: in Haskell vordefiniert x in Haskell als x%y gedruckt. y Beispiele: Prelude> (3%4)*(4%5) 3 % 5 Prelude> 1%2+2%3 7 % 6 Datenkonversionen: z.b. torational, truncate. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 85
n-tupel von Objekten Als Verallgemeinerung von Paaren (t 1,..., t n ) ist n-tupel von t 1,..., t n Beispiele (1,2,3,True) (1,(2,True),3) ("hallo",false) (fakultaet 100,\x-> x) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 86
Zusammengesetzte Objekte: Datentypen Für Datentypen benötigt man: Datenkonstruktor(en) Datenselektor(en) Beispiel Paarkonstruktor s, t (s, t) Paarselektoren fst, snd Eigenschaften: fst(s, t) = s und snd(s, t) = t. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 87
Beispiel n-tupel n-tupelkonstruktor t 1,..., t n (t 1,..., t n ) Tupelselektoren n Selektoren: pro Stelle ein Selektor n-tupel haben einen impliziten Konstruktor: (.,...,.) }{{} n P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 88
Definition der Selektoren Muster (pattern) statt Selektoren. Muster sind syntaktisch dort erlaubt, wo formale Parameter (Variablen) neu eingeführt werden: in Funktionsdefinitionen, in Lambda-Ausdrücken und in let-ausdrücken. Beispiel-Definitionen von Selektoren mittels Muster fst (x,y) = x snd (x,y) = y selektiere_1_von_3 (x1,x2,x3) = x1 selektiere_2_von_3 (x1,x2,x3) = x2 selektiere_3_von_3 (x1,x2,x3) = x3 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 89
Beispiel: Typen von Selektoren, Konstruktoren, Tupeln (1, 1) :: (Integer, Integer) (1, (2, True)) :: (Integer, (Integer, Bool)) (.,...,.) :: α 1 α 2... α n (α 1, α 2,..., α n ) }{{} n selektiere_3_von_3 :: (α 1, α 2, α 3 ) α 3 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 90
Benutzerdefinierte Konstruktoren In Haskell mittels data-anweisung Beispiel data Punkt = Punktkonstruktor Double Double deriving (Show, Eq) data Strecke = Streckenkonstruktor Punkt Punkt deriving (Show, Eq) data Viertupel a b c d = Viertupelkons a b c d deriving (Show, Eq) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 91
Muster (pattern) Nutzen der Muster: Gleichzeitiges und tiefes Selektieren Ersatz für Selektoren Syntax der Muster: Muster ::= Variable ( Muster ) Konstruktor (n) Muster... Muster }{{} n ( Muster,..., Muster ) Kontextbedingung: in einem Muster keine Variable doppelt P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 92
Auswertung unter Benutzung von Mustern Mustervergleich: Anpassen des Objekts an das Muster gleichzeitige Selektion mittels impliziter let-bindungen I.a. vorher Auswertung des Objekts erforderlich Beispiel (x,y,(u,v)) anpassen an: (1,2,(3,4)) ergibt: let {x = 1;y = 2;u = 3;v = 4} in... (x,y,(u,v)) anpassen an: (1,2,True) ergibt: Fehler. Kann nicht vorkommen wegen Typcheck. (x,y,u) anpassen an: (1,2,(4,5)) ergibt: let {x = 1; y = 2;u = (4,5)} in... P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 93
Auswertung unter Benutzung von Mustern (2) Beispiel (x,y) anpassen an: (1,fakt 100) ergibt: {let {x = 1; y = fakt 100} in... (x,y) anpassen an: (fst (1,2), snd (fakt 100,fakt 200)) ergibt : let {x = fst (1,2); y = snd (fakt 100, fakt 200)} in... P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 94
Musteranpassung anpassen Muster Ausdruck Ergebnis ist eine Menge von Bindungen: anpassen Kon Kon = (passt; aber keine Bindung notwendig.) anpassen x t = {x t}: (x wird an t gebunden.) anpassen (Kon p 1... p n ) (Kon t 1... t n ) = (anpassen p 1 t 1 )... (anpassen p n t n ) anpassen (Kon s 1... s n ) (Kon t 1... t m = Fail, wenn Kon Kon. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 95
Musteranpassung: weitere Möglichkeiten Variablen für Zwischenstrukturen in Mustern: Beispiel (x,y@(z_1,z_2)) anpassen an (1, (2,3)) ergibt: x = 1, y = (2,3), z_1 = 2, z_2 = 3. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 96
Benutzerdefinierte Typnamen mit Parametern Beispiel Punkt, Strecke, Polygonzug data Punkt a = Punkt a a deriving(show,eq) data Strecke a = Strecke (Punkt a) (Punkt a) deriving(show,eq) data Vektor a = Vektor a a deriving(show,eq) data Polygon a = Polygon [Punkt a] deriving(show,eq) Typ und Konstruktor können gleiche Namen haben. Der Parameter a kann jeder Typ sein: z.b.: Float, Int, aber auch [[(Int, Char)]] P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 97
Funktionen auf Punkt, Strecke, Polygonzug addierevektoren::num a => Vektor a -> Vektor a -> Vektor a addierevektoren (Vektor a1 a2) (Vektor b1 b2) = Vektor (a1 + b1) (a2 + b2) streckenlaenge (Strecke (Punkt a1 a2) (Punkt b1 b2)) = sqrt (frominteger ((quadrat (a1 - b1)) + (quadrat (a2-b2)))) verschiebestrecke s v = let (Strecke (Punkt a1 a2) (Punkt b1 b2)) = s (Vektor v1 v2) = v in (Strecke (Punkt (a1+v1) (a2+v2)) (Punkt (b1+v1) (b2+v2))) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 98
Funktionen auf Punkt, Strecke, Polygonzug (2) teststrecke = (Strecke (Punkt 0 0) (Punkt 3 4)) test_streckenlaenge = streckenlaenge (verschiebestrecke teststrecke (Vektor 10 (-10))) -------------------------------------------------------- streckenlaenge teststrecke <CR> > 5.0 test_streckenlaenge <CR> > 5.0 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 99
Typen der Funktionen addierevektoren :: Num a => Vektor a -> Vektor a -> Vektor a streckenlaenge :: Num a => Strecke a -> Float test_streckenlaenge :: Float verschiebestrecke :: Num a => Strecke a -> Vektor a -> Strecke a P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 100
Summentypen und Fallunterscheidung Summentyp: definiert durch die Bedingung: hat mehr als einen Konstruktor Beispiele: Bool mit True False data Wahrheitswerte = Wahr Falsch Aufzählungstyp: data Farben = Rot Gruen Blau Weiss Schwarz data Kontostand = Dm (Integer) Euro (Integer) Dollar (Integer) SFranken (Integer) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 101
Funktionsdefinition mit mehreren Mustern: Beispiele: und1 Wahr Falsch = Falsch und1 Wahr Wahr = Wahr und1 Falsch Falsch = Falsch und1 Falsch Wahr = Falsch oder und2 Wahr x = x und2 Falsch x = Falsch oder und3 Wahr x = x und3 Falsch _ = Falsch -- Joker, Wildcard P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 102
Fallunterscheidung mit case Für Summentypen ist eine neue Reduktionsregel notwendig: Syntax: case Ausdruck of { Muster -> Ausdruck ;... ; Muster -> Ausdruck } Einschränkung: nur einfache Muster: K x 1... x n Kontextbedingung: die Muster müssen vom Typ her passen. Beispiel; und4 ist äquivalent zu und2, und3) und &&: und4 x y = case x of True -> y; False -> False nichtleer lst = case lst of [] -> False (x:t) -> True P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 103
case: Gültigkeitsbereich, FV und GV F V (case s of (c 1 x 11... x 1n1 t 1 );... ; (c k x k1... x knk t k )) = F V (s) F V (t 1 ) \ {x 11,... x 1n1 }... F V (t k ) \ {x k1,... x knk } GV (case s of (c 1 x 11... x 1n1 t 1 );... ; (c k x k1... x knk t k )) = GV (s) GV (t 1 ) {x 11,... x 1n1 }... GV (t k ) {x k1,... x knk } P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 104
case: Gültigkeitsbereich, Beispiel F V (case x of True -> y; False -> False) = {x, y} F V (case x of (Punkt u v) -> u) = {x} GV (case x of (Punkt u v) -> u) = {u, v} P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 105
Fallunterscheidung if-then-else Die Definition mein_if x y z = case x of True -> y; False -> z ist äquivalent zum if. then. else P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 106
Reduktionsregel zum case case-reduktion (case (c t 1... t n ) of... (c x 1... x n s)...) let {x 1 = t 1 ;... ; x n = t n } in s P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 107
case-reduktion: Beispiele dmoderdollar x = case x of (Dm wert) -> True; (Dollar wert) -> True; Euro _ -> False; SFranken _ -> False ---------------------------------- dmoderdollar (Dollar 10) --> case (Dollar 10) of (Dm wert) -> True; (Dollar wert) -> True; Euro _ -> False; SFranken _ -> False --> let wert = 10 in True --> True P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 108
Reduktionsregel zum case dmoderdollarwert x = case x of (Dm wert) -> wert; (Dollar wert) -> wert; Euro _ -> 0; SFranken _ -> 0 --------------------------- dmoderdollarwert (Dollar 10) --> case (Dollar 10) of (Dm wert) -> wert; (Dollar wert) -> wert; Euro _ -> 0; SFranken _ -> 0 --> let wert = 10 in wert --> let wert = 10 in 10 --> 10 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 109
Funktionsdefinitionen: Strategie Fallunterscheidungen mit Mustern in Funktionsdefinitionen: können als case-ausdrücke geschrieben werden. Haskell erlaubt überlappende Muster Musteranpassungsstrategie in Funktionsdefinitionen mit Mustern und Wächtern: Muster von oben nach unten, bis Muster passt und Wächter = True Es gilt: Diese Strategie ist zur Compilezeit in geschachtelte case-ausdrücke transformierbar P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 110
Funktionsdefinitionen: Beispiel f (Euro x) = "Euro" f (Dollar x) = "US Dollar" f x = "andere " f y = case y of (Euro x)-> "Euro"; (Dollar x)-> "Dollar"; (Dm x)-> "andere"; (SFranken x) -> "andere"; P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 111
Auswertung in Haskell Kombination von Transformation und Auswertung: Haskell- Programm Entzuckerung Programm in Kernsprache Syntaxanalyse Syntaxbaum des Programms transformierter Syntaxbaum Auswertung (operationelle Semantik) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 112
Entzuckerung: Beispiel map f [] = [] map f (x:xs) = f x : map f xs kann man transformieren zu: map f lst = (case lst of [] -> []; (x:xs) -> f x : map f xs) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 113
Bemerkungen zu Church-Rosser-Sätzen Die Church-Rosser-Sätze gelten bei nicht-rekursivem let wenn keine Konstruktoren benutzt werden. Die Church-Rosser-Sätze gelten nicht mehr bei rekursivem let analoge Aussagen gelten noch Hierzu benötigt man das Konzept der Verhaltensgleichheit von Ausdrücken P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 114
Verhaltensgleichheit Man kann eine Verhaltensgleichheit definieren, so dass gilt: verschiedene Basiswerte a, b sind nicht verhaltensgleich: a b a b man kann Gleiches durch Gleiches ersetzen: s t P [s] P [t] Reduktion erhält Verhaltensgleichheit: s t s t Die Folgerungen sind weitreichend: Z.B. ist es korrekt, alle Auswertungen bereits im Compiler zu machen. Das ist in anderen Programmiersprachen nur in sehr eingeschränkten Fällen korrekt. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 115
Rekursive Datenobjekte: Listen, Bäume,... Listen: Nochmal Eine eigene Definition des Datentyps Liste: data Liste a = Leereliste ListenKons a (Liste a) a : Typ der Objekte in der Liste Rekursiver Datentyp! P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 116
Listen in Haskell Listen sind in Haskell eingebaut mit syntaktischer Sonderbehandlung So würde die Definition aussehen data [a] = [] a : [a] (Im Prinzip korrekt) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 117
Listenausdrücke, (list comprehensions) Syntax: [ Ausdruck " " Generator Filter {, { Generator Filter }} ]. Analog zu Mengenausdrücken, Z.B. {x x < 3, x IN} aber Reihenfolge der Listenelemente im Resultat wird festgelegt. P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 118
Beispiele: [x x <- xs] = xs [f x x <- xs] = map f xs [x x <- xs, p x] = filter p xs [(x,y) x <- xs, y <-ys] = xs ys (Kreuzprodukt) für endliche Listen [y x <- xs, y <-x] = concat xs P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 119
Listen-Komprehensionen [Resultatausdruck Generatoren,Testfunktionen] Generator: v <- liste generiert Elemente von liste Prädikat: Test auf True/False. Element wird akzeptiert/nicht akz. Wirkungsweise: die Generatoren liefern nach und nach die Elemente der Listen. Wenn alle Prädikate zutreffen, wird Resultatausdruck in die Resultatliste aufgenommen. neue lokale Variablen sind möglich. Deren Geltungsbereich ist rechts von der Einführung und im Resultatausdruck und P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 120
List-Komprehensionen: Beispiel Zahlen, die nicht durch 2,3,5,7 teilbar sind zwischen 2 und 100: [x x<-[2..100], not (even x), not (x mod 3 == 0), not ( x mod 5 == 0), not(x mod 7 == 0)] [11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97] P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 121
List-Komprehensionen: Beispiel [(x,y) x <- [1..10], even x, y <- [2..6], x < y] Resultat: [(2,3),(2,4),(2,5),(2,6),(4,5),(4,6)] Begründung: Erzeugungsreihenfolge: x 1 2 2 2 2 2 3 4 4 4 4 4 5 6... y 2 3 4 5 6 2 3 4 5 6 2...? N N Y Y Y Y N N N N Y Y N N... P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 122
List-Komprehensionen: Beispiel [(x,y) x <- [1..10], y <- [1..x]] [(1,1), (2,1),(2,2), (3,1),(3,2),(3,3), (4,1),(4,2),(4,3),(4,4), (5,1),(5,2),(5,3),(5,4),(5,5), (6,1),(6,2),(6,3),(6,4),(6,5),(6,6), (7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(7,7), (8,1),(8,2),(8,3),(8,4),(8,5),(8,6),(8,7),(8,8), (9,1),(9,2),(9,3),(9,4),(9,5),(9,6),(9,7),(9,8),(9,9), (10,1),(10,2),(10,3),(10,4),(10,5),(10,6),(10,7),(10,8),(10,9),(10,10)] P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 123
Beispiel: einfache geometrische Algorithmen Fläche eines Dreiecks Polygonfläche Test auf Konvexität Generelles Problem der geometrischen Algorithmen: Sonderfälle Beispiel Fläche eines regelmäßigen n-ecks Fläche des Umkreises Vergleich P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 124
Funktionen zu geometrischen Algorithmen konvexer Polygonzug p 1,..., p 5 p5 p4 p3 p1 p2 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 125
Funktionen zu geometrischen Algorithmen data Punkt a = Punkt a a deriving(show,eq) data Strecke a = Strecke (Punkt a) (Punkt a) deriving(show,eq) data Vektor a = Vektor a a deriving(show,eq) data Polygon a = Polygon [Punkt a] deriving(show,eq) -- polgonflaeche data Polygon a = Polygon [Punkt a] deriving(show,eq) -- Annahme: Polygonz"uge sind geschlossen polyflaeche poly = if ist_konvex_polygon poly then polyflaeche_r poly else error "Polygon ist nicht konvex" polyflaeche_r (Polygon (v1:v2:v3:rest)) = dreiecksflaeche v1 v2 v3 + polyflaeche_r (Polygon (v1:v3:rest)) polyflaeche_r _ = fromint 0 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 126
Funktionen zu geometrischen Algorithmen(2) dreiecksflaeche v1 v2 v3 = let a = abstand v1 v2 b = abstand v2 v3 c = abstand v3 v1 s = 0.5*(a+b+c) in sqrt (s*(s-a)*(s-b)*(s-c)) abstand (Punkt a1 a2 ) (Punkt b1 b2 ) = let d1 = a1-b1 d2 = a2-b2 in sqrt (d1^2 + d2^2) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 127
Funktionen zu geometrischen Algorithmen(3) Normierung: Elimination von gleichen Punkten Elimination von kollinearen Tripeln poly_norm (Polygon x) = let eqnorm = (poly_normeq_r x) kollnorm = poly_norm_koll2 (poly_norm_koll eqnorm) in Polygon kollnorm poly_normeq_r [] = [] poly_normeq_r [x] = [x] poly_normeq_r (x:rest@(y:_)) = if x == y then poly_normeq_r rest else x: poly_normeq_r rest P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 128
Funktionen zu geometrischen Algorithmen (4) poly_norm_koll (x:rest1@(y:z:tail)) = if poly_drei_koll x y z then poly_norm_koll (x:z:tail) else x:poly_norm_koll rest1 poly_norm_koll rest = rest poly_norm_koll2 (x:rest) = if length rest < 2 then x:rest else let y = last rest z = rest!! (length rest -2) in if poly_drei_koll z y x then rest else if poly_drei_koll y x (rest!! 0) then rest else x:rest P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 129
Funktionen zu geometrischen Algorithmen (5) --testet x,y,z auf Kollinearitaet: poly_drei_koll (Punkt x1 x2) (Punkt y1 y2) (Punkt z1 z2) = (z1-y1)*(y2-x2) == (y1-x1)*(z2-y2) --- (z1-y1)/(z2-y2) == (y1-x1)/(y2-x2) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 130
Funktionen zu geometrischen Algorithmen (6) -- testet Konvexitaet: aber nur gegen den Uhrzeigersinn. ist_konvex_polygon (Polygon []) = True ist_konvex_polygon (Polygon [p,q]) = True ist_konvex_polygon (Polygon (alles@(p:q:polygon))) = ist_konvex_polygonr (alles ++ [p,q]) ist_konvex_polygonr (p1:rest@(p2:p3:rest2)) = ist_konvex_drehung_positiv p1 p2 p3 && ist_konvex_polygonr rest ist_konvex_polygonr _ = True ist_konvex_drehung_positiv (Punkt a1 a2) (Punkt b1 b2) (Punkt c1 c2) = let ab1 = a1-b1 ab2 = a2-b2 bc1 = b1-c1 bc2 = b2-c2 in ab1*bc2-ab2*bc1 > 0 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 131
Geometrische Algorithmen. Beispiel *Main> testpolygon Polygon [Punkt 1 1,Punkt 2 2,Punkt 3 3,Punkt 3 3, Punkt 0 3,Punkt (-1) (-1),Punkt 0 (-2)] *Main> poly_norm testpolygon Polygon [Punkt 1 1,Punkt 3 3,Punkt 0 3,Punkt (-1) (-1),Punkt 0 (-2)] *Main> P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 132
Funktionen zu geometrischen Algorithmen: Vieleck vieleck n = Polygon [Punkt (cos (2.0*pi*i/n)) (sin (2.0*pi*i/n)) i <- [1.0..n]] vieleckflaeche n = polyflaeche (vieleck n) vieleck_zu_kreis n = let kreis = pi vieleck = vieleckflaeche n ratio = vieleck / kreis in (n,kreis, vieleck,ratio) *Main> vieleckflaeche 100000 3.1415926515204107 *Main> pi 3.141592653589793 P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 133
Funktionen auf Listen: fold foldl (Linksfaltung) foldr (Rechtsfaltung) Argumente: eine zweistellige Operation ein Anfangselement (Einheitselement) die Liste foldl foldl f z [] foldl f z (x:xs) :: (a -> b -> a) -> a -> [b] -> a = z = foldl f (f z x) xs foldr foldr f z [] foldr f z (x:xs) :: (a -> b -> b) -> b -> [a] -> b = z = f x (foldr f z xs) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 134
foldl und foldr foldl e [a 1,..., a n ] entspricht ((... ((e a 1 ) a 2 )... ) a n ). foldr e [a 1,..., a n ] entspricht a 1 (a 2 (... (a n e))) Wenn dann assoziativ, e Rechts- und Linkseins zu, und Liste lst endlich, gleicher Wert für (foldl e lst) und (foldr e lst) P raktische Informatik 1, W S 2004/05, F olien Haskell 3, (8. Dezember2004) Seite 135