Grundprinzipien der funktionalen Programmierung
Funktionen haben keine Seiteneffekte Eine Funktion berechnet einen Ausgabewert der nur von den Eingabewerten abhängt: 12 inputs + output 46 34 2
Nicht nur Zahlen, auch Bilder A function to flip a picture in a vertical mirror: input flipv output 3
Mehr Funktionen auf Bildern A function to invert the colours in a picture: invertcolour 4
Mehr Funktionen auf Bildern A function to superimpose two pictures: superimpose 5
Mehr Funktionen auf Bildern A function to put one picture above another: above 6
Mehr Funktionen auf Bildern A function to put two pictures side by side: sidebyside 7
Typen Ein Typ ist eine Menge von Werten, wie Zahlen oder Bilder. Auf alle Werte eines Typs sind die gleichen Funktionen anwendbar: Wir können zwei Zahlen addieren, nicht aber eine Zahl und ein Bild oder zwei Bilder. 8
Alles hat einen Typ Werte haben Typen: true : bool 1 : int Funktionen haben Typen: + : int -> int -> int above: picture -> picture -> picture 9
Klammerung von Typen Implizite Klammerung: T1 -> T2 -> T = T1 -> (T2 -> T) + : int -> int -> int + : (int -> int) -> int integrate: (real -> real) -> real -> real -> real integrate: real -> real -> real -> real -> real 10
Auswertung von Ausdrücken durch Termersetzung Ausdruck (7-3)+ 2 (7-3)+2 4+2 Auswertung Wert 4+2 6 11
sidebyside (invertcolour ) sidebyside Auswertung mit Bildern 12
Auswertungsstrategien f x = 1 g x = g x Eager evaluation / Call-by-value / Eifrige Auswertung: f(g 1) => f(g 1) =>... Prinzip: Zuerst die Parameter, dann die Funktion Lazy evaluation / Call-by-need / Verzögerte Auswertung: f(g 1) => 1 Prinzip: Parameter erst, wenn sie gebraucht werden 13
Auswertungsstrategien Wenn eifrige Auswertung terminiert, dann auch verzögerte Auswertung, und beide berechnen den gleichen Wert. SML: Eager evaluation Haskell: Lazy evaluation 14
Ausdrücke (Terme) Ein Ausdruck ist entweder atomar (z.b. x, true, 42) oder zusammengesetzt: f a1... an wobei f, a1,..., an Ausdrücke passenden Typs sind: f : T1 ->... -> Tn -> T ai : Ti 15
Klammerung von Ausdrücken Implizite Klammerung: f a b = (f a) b Funktionsanwendung ist nach links geklammert sin cos pi = (sin cos) pi sin(cos pi) integrate sin pi = (integrate sin) pi integrate (sin pi) 16
Präfix und Infix Infix: 3+4 ist Abkürzung für + 3 4 Präfix bindet stärker als Infix: f x+1 = (f x) + 1 17
Funktionale Programmierung in SML
The Web page... SML distributions and documentation. Background material: books, FAQs, etc... 19
Wertedefinitionen in SML Allgemeines Format: val name = expression Beispiele: val null = 0+0; val Horse = above horse horse; 20
Funktionsdefinitionen in SML Einfaches Format: fun name x1... xn = expression Beispiel: fun sum n = if n=0 then 0 else n+sum(n-1); 21
Funktionsdefinitionen in SML Mit Pattern Matching: fun name pat... pat = expression name pat... pat = expression... Beispiel: fun sum 0 = 0 sum n = n + sum(n-1) Reihenfolge der Gleichungen wichtig! 22
Lokale Definitionen: let let val x = 42 in x+x end => 42+42 => 84 let fun f x = x+1 in f(f 5) end... => 7 23
Typen in SML
Typinferenz SML berechnet automatisch den Typ jedes Ausdrucks val x = 42; >... : int fun f x = x+1; >... : int -> int 25
Polymorphismus Der Typ einer Funktion kann Typvariablen enthalten: a, b, name Ein solcher Typ heisst polymorph. fun f x = x; >... : a -> a f 5; > 5 : int f true; > true : bool 26
Polymorphismus fun S x y z = (x z) (y z); Was ist der Typ der Funktion? Typinferenz berechnet den allgemeinsten Typ. Polymorphismus ist ein Abstraktionsprinzip. 27
Basistypen bool int, real char, string 28
Booleans Everything is true or false 29
Vordefinierte Boolesche Operatoren if x:bool then y:t else z:t a andalso b = if a then b else false a orelse b = if a then true else b not a = if a then false else true 30
Beispiel Pattern Matching fun xor true true = false xor false true = true xor true false = true xor false false = false; 31
Arithmetik: int und real 42 : int 42.0 : real Funktionen: ~ + - * / div mod... Vergleiche: < <= > >= Infix syntax: 3 + 4 Präfix syntax: op + (3,4) op + : int * int -> int 32
Überladung Die meisten vordefinierten Operatoren (+,..., <,...) sind überladen, dh sowohl für int als auch real definiert. Benutzerdefinierte Funktionen dürfen nicht überladen sein: fun doppel x = x+x; > Fehlermeldung wg Überladung fun doppeli(x:int) = x+x; fun doppelr(x:real) = x+x; 33
Primitive Rekursion auf int Ein Schema oder Schablone: fun f 0 =... f n =... f(n-1)... Beispiel: 2er Potenzen. fun power2 0 = 1 power2 n = 2 * power2 (n-1); 34
Wie viele Teile nach n Schnitten? 35
Wie viele Teile nach n Schnitten? 0 Schnitte: 1 Teil. Mit dem n-ten Schnitt erhält man n weitere Teile: fun pieces 0 = 1 pieces n = pieces(n-1) + n; 36
Nicht alles ist primitiv rekursive fun ggt 0 n = n ggt m n = ggt (n mod m) m; 37
Characters Letters, digits and special characters. Literal characters are: #"a" Special characters are: #"\n" #"\t" #"\\" #"\" newline tab backslash double quote 38
Characters und strings "This is a string" : string Standardfunktionen: explode: string -> char list implode: char list -> string chr :: int -> char ord :: char -> int 39
Paare und Tupel (1,2) : int * int (1,2,true) : int * int * bool (1,(2,true)) : int * (int * bool) ((1,2),true) : (int * int) * bool fun fst(x,y) = x; fun snd(x,y) = y; fun swap(x,y) = (y,x); fun pair x = (x,x); 40
Listen T list: Listen von Element des Typs T Leere Liste: [] Cons : x :: xs Endliche Liste: [1,2,3] = 1::2::3::[] = 1::(2::(3::[])) 41
Zusammenfassung: Typen Τ ::= bool int... T * T T list (T,...,T)Typkonstruktor T -> T (T) Typvariable 42
Gleichheit op = : a * a -> bool a ist eine Typvariable über Gleichheitstypen. Gleichheitstypen sind (in erster Näherung) alle Typen ohne ->. 1 = 1 : bool not = not : Typfehler 43
Funktionen
Partielle Anwendung Sei f: T1 -> T2 -> T und a1:t1. Dann ist f a1 : T2 -> T eine partielle Anwendung. Bsp: Gegeben parser : grammar -> string -> bool Cgram : grammar kann man definieren val Cparser = parser Cgram > Cparser : string -> bool 45
Currying (nach Haskell B. Curry) fun f x y =... > : T1 -> T2 -> T fun f(x,y) =... > : T1 * T2 -> T f ist curried f ist gepaart 46
Funktionen höherer Stufe = Funktionen als Parameter integrate: (real -> real) ->... sort: ( a -> a -> bool) ->...... 47
Funktionen als Werte Lambda Kalkül: λx.e SML: fn x => e : T -> U falls x:t und e:u x ist formaler Parameter e ist Funktionskörper, d.h. Resultat Bsp: fn x => x+1 : int -> int (fn x => x+1) 41 => 42 48
fun, fn und val Parameter kann man von links nach rechts verschieben: fun f x y = e fun f x = fn y => e ist äquivalent zu fun ist val rec: fun g x = e val rec g = fn x => e ist äquivalent zu 49
Programmierung, Spezifikation und Verifikation mit Listen
Primitive Rekursion auf list Ein Schema oder Schablone: fun f [] =... f (x::xs) =... f xs... Beispiel: fun length [] = 1 length (x::xs) = length xs + 1; 51
Wichtige Funktionen auf Listen fun [] @ ys = ys (x::xs) @ ys = x :: (xs @ ys); fun concat [] = [] concat(xs::xss) = xs @ concat xss; Informell: concat [xs1,...,xsn] = xs1 @... @ xsn fun rev [] = [] rev (x::xs) = rev xs @ [x]; 52
map und filter fun map f [] = [] map f (x::xs) = f x :: map f xs Informell: map f [x1,...,xn] = [f x1,...,f xn] fun filter p [] = [] filter p (x::xs) = if p x then x :: filter p xs else filter p xs 53
Taking and... fun take n [] = [] take n (x:xs) = if n <= 0 then [] else x :: take (n-1) xs; fun takewhile p [] = [] takewhile p (x:xs) = if p x then x :: takewhile p xs else []; 54
... dropping Analog: drop : int -> a list -> a list dropwhile : ( a -> bool) -> a list -> a list 55
Zipping fun zipwith f (x::xs) (y::ys) = f x y :: zipwith f xs ys zipwith _ = []; Anwendung: zipwith??? [x1,...] [y1,...] = [(x1,y1),...] zipwith??? [x1,...] [y1,...] = [x1+y1,...] 56