Funktionale Programmierung Jörg Kreiker Uni Kassel und SMA Solar Technology AG Wintersemester 2011/2012
2 Teil II Typen mit Werten und Ausdruck, sogar listenweise
3 Haskell Programme Programm Module ein Main Modul Deklarationen Typ/Wert-Bindungen decls Ausdrücke ein main Ausdruck exp
4 Ausdrücke haben einen Typ: statische Semantik werden reduziert zu Werten: dynamische Semantik sind auch Werte spezieller Wert : Fehler, Nichtterminierung einfache Ausdrücke: Konstanten, Variablen, Konstruktoren exp c x K
5 Werte vollreduzierte Ausdrücke Basiswerte Konstruktoren mit vollreduzierten Argumenten λ-ausdrücke Werte werden nur reduziert bei Musterabgleich (pattern matching) Ein/Ausgabe Haskell ist lazy Wertdomäne: Val
6 Werte und Typen selbstgemacht Summentypen Parametrierte Typen, Produkttypen Rekursive Typen
7 Summentypen data Color = Red Blue Color: ein nullstelliger Typkonstruktor Red, Blue: nullstellige Wertkonstruktoren Red :: Color Bekannte Summentypen:Int, Char, Bool Achtung: Konstruktoren immer großschreiben!
8 Parametrierte Typen data Quad = Square Int Rect Int Int Quad: nullstelliger Typkonstruktor Square: einstelliger Wertkonstruktor Rect: zweistelliger Wertkonstruktor Typ von Square: Int Quad Typ von Rect: Int Int Quad Bekannte parametrierte Typen:Produkttypen wie Tupel Konstruktoren (Wert und Typ): (), (,), (,,),...
9 Rekursive Typen data Tree a = Emp Node a (Tree a) (Tree a) Tree: einstelliger Typkonstruktor mit kind Node dreistelliger Wertkonstruktor vom Typ α Tree α Tree α Tree α Bekannte rekursive Typen: Listen Wertkonstruktoren: [] und (:) Typkonstruktor: []
STOP 10
11 Funktionen exp... λx exp sind Werte genauso wie Basiswerte auch genannte λ Abstraktion voll reduziert Currying: λx 1 x 2... x k exp als Abkürzung von λx 1 λx 2... λx k exp
Ausdruck: Anwendungen exp... exp 1 exp 2 nicht reduzierte Ausdrücke (haben einen Redex) dynamische Semantik: exp 1 = λx exp Werte exp in einer Umgebung aus, in der x an exp 2 gebunden ist exp 2 wird nicht ausgewertet! Spezialfall: exp 1 wertet zu Konstruktor aus
13 Einschub: Auswertungsstrategien Strikt Alle Argumente werden ausgewertet, bevor sie an die formalen Parameter gebunden werden. Nicht strikt Argumente werden nur bei Bedarf ausgewertet Implementierungen call-by-value: strikt, alle Argumente auswerten Beispiele: C, Java, ML, Pascal, C++ call-by-need: nicht strikt, Auswertungen werden gespeichert (Haskell) call-by-name: nicht strikt, aber wie Inlining call-by-reference: strikt, Speicherort der Parameter wird übergeben Beispiele: Pascal, C++
Operatoren Infix Operatoren wie +, -, ++, wie normale Funktionen wenn in Klammern (+) 1 3 foldr (++) [] [[1,2],[3,4],[5,6]] Operatoren keine alphanumerischen Zeichen Funktionen in backquotes benutzbar wie Operatoren let plus a b = a + b in 1 plus 2 let conc = foldr (++) in [] conc [[1,2],[3,4]]
15 Sections Partiell angewendete Operatoren (op exp) λx x op exp : Abkürzung (syntactic sugar) (exp op) λx exp op x let m = \x y -> x-y in (2 m ) 5 map (+1) [1,2,3]
STOP 16
Let Ausdrücke exp let decls in exp decls pat 1 = exp 1 ;... ; pat k = exp k decls: Liste lokaler Deklarationen Muster oder Funktionen können gebunden werden lexikographischer Scope verschränkt rekursiv Layout Regel: alles was nach let in derselben Spalte startet
18 Deklarationen Deklarationen erzeugen Bindungen [x v] Umgebung: Menge von Bindungen E : Id Val Bindungen entstehen durch Musterabgleich: pat exp dynamische Semantik von let p = e in e in Umgebung E Werte e in E p e aus verdeckt bestehende Bindungen
19 Beispiele let x=1 in x+1 = 2 let (2,x) = (2,1) in x+1 = 2 let (2,x) = (1,1) in x+1 = let (2,x) = (1,1) in 1 = 1 let x=5 in let x=3 in x+x = 6 let x=5 in (let x=3 in x)+x = 8 let [x,y,z] = 1: in x = 1 let e = 0 : [n+1 n <- o] o = [n+1 n <- e] in (take 10 e, take 10 o)
STOP 20
21 Listen: map und fold Die wichtigsten Funktionen auf Listen sind definierbar durch map und fold. map f [] = [] map f (x:xs) = (f x):(map f xs) foldr f res [] = res foldr f res (x:xs) = f x (foldr f res xs)
comprehensions Jedes q i ist ein [ e q 1,..., q n ] Generator: p e, wobei p ein Muster von Typ τ und e ein Ausdruck von Typ [τ] ist; oder eine lokale Deklaration: let decl; oder ein Wächter: exp vom Typ Bool Beispiele nats = 1 : [n+1 n <- nats]: Liste aller natürlicher Zahlen [x x <- nats, x mod 2 == 0]: Liste aller geraden Zahlen fib = 1 : 1 : [a+b (a,b) <- zip fib (tail fib)]: Fibonacci Zahlen
23 comprehensions als syntaktischer Zucker [ e True ] [e] [ e q ] [e q, True] [ e b, Q ] if b then [e Q] else [] [ e p l, Q ] let ok p = [e Q] ok = [] in concatmap ok l [ e let decl, Q ] let decl in [e Q] Bemerkung: concatmap f [] = [] concatmap f (x:xs) = (f x) ++ concatmap f xs
STOP 24