Fahrplan Teil I: Grundlagen Praktische Informatik 3 Einführung in die Funktionale Programmierung Rekursion als Berechnungsmodell Rekursive Datentypen, rekursive Funktionen Vorlesung vom 12.11.2008: Typvariablen und Polymorphie Typvariablen und Polymorphie Funktionen höherer Ordnung Christoph Lüth Standarddatentypen Teil II: Abstraktion WS 08/09 Teil III: Beispiele, Anwendungen, Ausblicke Christoph Lüth: Praktische Informatik 3 1 WS 08/09 Inhalt Christoph Lüth: Praktische Informatik 3 1 WS 08/09 Letzte Vorlesung: Zeichenketten Eine Zeichenkette ist Letzte Vorlesung: rekursive Datentypen entweder leer (das leere Wort ) Diese Vorlesung: oder ein Zeichen und eine weitere Zeichenkette Abstraktion über Typen: Typvariablen und Polymorphie data MyString = Empty | Cons Char MyString Typinferenz: Wie bestimme ich den Typ eines Ausdrucks? Christoph Lüth: Praktische Informatik 3 2 WS 08/09 Funktionen auf Zeichenketten Christoph Lüth: Praktische Informatik 3 3 WS 08/09 Weiteres Beispiel: Liste von Zahlen Länge: len :: MyString-> Int len Empty = 0 len (Cons c str) = 1+ len str Eine Liste von Zahlen ist entweder leer (das leere Wort ) Verkettung: cat :: MyString-> MyString-> MyString cat Empty t = t cat (Cons c s) t = Cons c (cat s t) oder eine Zahl und eine weitere Liste data IntList = Empty | Cons Int IntList Umkehrung: rev :: MyString-> MyString rev Empty = Empty rev (Cons c t) = cat (rev t) (Cons c Empty) Christoph Lüth: Praktische Informatik 3 4 WS 08/09 Christoph Lüth: Praktische Informatik 3 Funktionen auf Zahlenlisten 5 WS 08/09 Typvariablen Länge: Typvariablen abstrahieren über Typen len :: IntList-> Int len Empty = 0 len (Cons c str) = 1+ len str data List a = Empty | Cons a (List a) Verkettung: a ist eine Typvariable cat :: IntList-> IntList-> IntList cat Empty t = t cat (Cons c s) t = Cons c (cat s t) a kann mit Char oder Int instantiiert werden List a ist ein polymorpher Datentyp Typvariable a wird bei Anwendung instantiiert Umkehrung: Signatur der Konstruktoren rev :: IntList-> IntList rev Empty = Empty rev (Cons c t) = cat (rev t) (Cons c Empty) Christoph Lüth: Praktische Informatik 3 6 Empty :: List a Cons :: a-> List a-> List a WS 08/09 Christoph Lüth: Praktische Informatik 3 7 WS 08/09 Polymorphe Funktionen Polymorphe Datentypen Typkorrekte Terme: Typ Empty List a Cons 57 Empty List Int Cons 7 (Cons 8 Empty) List Int Cons ’p’ (Cons ’i’ (Cons ’3’ Empty)) List Char Cons True Empty List Bool Verkettung von MyString: cat :: MyString-> MyString-> MyString cat Empty t = t cat (Cons c s) t = Cons c (cat s t) Verkettung von IntList: cat :: IntList-> IntList-> IntList cat Empty t = t cat (Cons c s) t = Cons c (cat s t) Nicht typ-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) Gleiche Definition, unterschiedlicher Typ wegen Signatur des Konstruktors: Zwei Instanzen einer allgemeineren Definition. Cons :: a-> List a-> List a Christoph Lüth: Praktische Informatik 3 8 WS 08/09 Christoph Lüth: Praktische Informatik 3 Polymorphe Funktionen 9 WS 08/09 11 WS 08/09 Tupel Polymorphie erlaubt Parametrisierung über Typen: Mehr als eine Typvariable: cat :: List a -> List a -> List a cat Empty ys = ys cat (Cons x xs) ys = Cons x (cat xs ys) data Pair a b = Pair a b Konstruktorname = Typname Typvariable a wird bei Anwendung instantiiert: cat (Cons 3 Empty) (Cons 5 (Cons 57 Empty)) cat (Cons ’p’ (Cons ’i’ Empty)) (Cons ’3’ Empty) Beispielterme: aber nicht Pair 4 "fünf" Pair (Cons True Empty) ’a’ Pair (3+ 4) (Cons ’a’ Empty) cat (Cons True Empty) (Cons ’a’ (Cons 0 Empty)) Typvariable: vergleichbar mit Funktionsparameter Christoph Lüth: Praktische Informatik 3 10 WS 08/09 Christoph Lüth: Praktische Informatik 3 Typinferenz Typinferenzregeln Bestimmung des Typen durch Typinferenz A, x :: t ` x :: t Formalismus: Typableitungen der Form A, x :: s ` e :: t Abs A ` \x -> e :: s -> t A ` x :: t A ` e :: s -> t A ` e 0 :: s App A ` e e 0 :: t A — Typumgebung (Zuordnung Symbole zu Typen) x — Term A ` e :: t, Typvariable α nicht frei in A Spec A ` e :: t αs t — Typ Herleitung durch fünf Basisregeln Notation: t Ax s x A ` f :: s A ` ci :: s A ` ei :: t Cases A ` case f of ci -> ei :: t x in t durch s ersetzt Lambda-Abstraktion: f = \x -> E für f x = E Christoph Lüth: Praktische Informatik 3 12 WS 08/09 Polymorphie in anderen Programmiersprachen: Java 13 WS 08/09 Polymorphie in anderen Programmiersprachen: C “Polymorphie” in C: void * Polymorphie in Java: Methode auf alle Subklassen anwendbar struct list { void *head; struct list *tail; } class List { public List(Object theElement, List n) { element = theElement; next = n; } public Object element; public List next; } Gegeben: int x = 7; struct list s = { &x, NULL }; Keine Typvariablen: String s = "abc"; List l = new List(s, null); s.head hat Typ void *: int y; y= *(int *)s.head; l.element hat Typ Object, nicht String String e = (String)l.element; Nicht möglich: head direkt als Skalar (e.g. int) Neu ab Java 1.5: Generics — damit echte Polymorphie möglich Christoph Lüth: Praktische Informatik 3 Christoph Lüth: Praktische Informatik 3 14 C++: Templates WS 08/09 Christoph Lüth: Praktische Informatik 3 15 WS 08/09 Vordefinierte Datentypen: Tupel und Listen Übersicht: vordefinierte Funktionen auf Listen ++ !! concat length head, last tail, init replicate take drop splitAt reverse zip unzip and, or sum product Eingebauter syntaktischer Zucker Tupel sind das kartesische Produkt data (a, b) = (a, b) (a, b) = alle Kombinationen von Werten aus a und b Auch n-Tupel: (a,b,c) etc. Listen data [a] = [] | a : [a] Weitere Abkürzungen: [x]= x:[], [x,y] = x:y:[] etc. Christoph Lüth: Praktische Informatik 3 16 WS 08/09 [a]-> [a]-> [a] [a]-> Int-> a [[a]]-> [a] [a]-> Int [a]-> a [a]-> [a] Int-> a-> [a] Int-> [a]-> [a] Int-> [a]-> [a] Int-> [a]-> ([a], [a]) [a]-> [a] [a]-> [b]-> [(a, b)] [(a, b)]-> ([a], [b]) [Bool]-> Bool [Int]-> Int (überladen) [Int]-> Int (überladen) Christoph Lüth: Praktische Informatik 3 Zeichenketten: String Verketten n-tes Element selektieren “flachklopfen” Länge Erster/letztes Element (Hinterer/vorderer) Rest Erzeuge n Kopien Nimmt ersten n Elemente Entfernt erste n Elemente Spaltet an n-ter Position Dreht Liste um Paare zu Liste von Paaren Liste von Paaren zu Paaren Konjunktion/Disjunktion Summe Produkt 17 WS 08/09 Beispiel: Palindrome String sind Listen von Zeichen: Palindrom: vorwärts und rückwärts gelesen gleich (z.B. Otto, Reliefpfeiler) type String = [Char] Signatur: Alle vordefinierten Funktionen auf Listen verfügbar. palindrom :: String-> Bool Syntaktischer Zucker zur Eingabe: Entwurf: [’y’,’o’,’h’,’o’] == "yoho" Rekursive Formulierung: erster Buchstabe = letzer Buchstabe, und Rest auch Palindrom Beispiel: Termination: Leeres Wort und monoliterales Wort sind Palindrome count :: Char-> String-> Int count c [] = 0 count c (x:xs) = if (c== x) then 1+ count c xs else count c xs Christoph Lüth: Praktische Informatik 3 18 Hilfsfunktionen: last: String-> Char, init: String-> String WS 08/09 Christoph Lüth: Praktische Informatik 3 Beispiel: Palindrome 19 WS 08/09 Zusammenfassung Implementierung: palindrom palindrom palindrom palindrom :: String-> Bool [] = True [x] = True (x:xs) = (x == last xs) && palindrom (init xs) Typvariablen und Polymorphie: Abstraktion über Typen Typinferenz (Hindley-Damas-Milner): Herleitung des Typen eines Ausdrucks Kritik: Vordefinierte Typen: Listen [a] und Tupel (a,b) Unterschied zwischen Groß- und kleinschreibung Nächste Woche: Funktionen höherer Ordnung palindrom (x:xs) = (toLower x == toLower (last xs)) && palindrom (init xs) Nichtbuchstaben sollten nicht berücksichtigt werden. Christoph Lüth: Praktische Informatik 3 20 WS 08/09 Christoph Lüth: Praktische Informatik 3 21 WS 08/09