Fahrplan I Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom 06.11.2012: Typvariablen und Polymorphie Christoph Lüth Universität Bremen Wintersemester 2012/13 Rev. 1861 Teil I: Funktionale Programmierung im Kleinen I Einführung I Funktionen und Datentypen I Rekursive Datentypen I Typvariablen und Polymorphie I Funktionen höherer Ordnung I I Funktionen höherer Ordnung II I Typinferenz I Teil II: Funktionale Programmierung im Großen I Teil III: Funktionale Programmierung im richtigen Leben 1 [28] Inhalt 2 [28] Ähnliche Datentypen der letzten Vorlesung I Letzte Vorlesung: rekursive Datentypen I Diese Vorlesung: I Abstraktion über Typen: Typvariablen und Polymorphie I Arten der Polymorphie: I Parametrische Polymorphie I Ad-hoc Polymorphie data L a g e r = L e e r e s L a g e r | L a g e r A r t i k e l Menge L a g e r data E i n k a u f s w a g e n = LeererWagen | E i n k a u f A r t i k e l Menge E i n k a u f s w a g e n data Path = Cons I d Path | Mt data M y S t r i n g = Empty | Cons Char M y S t r i n g I ein konstanter Konstruktor I ein linear rekursiver Konstruktor 3 [28] Ähnliche Funktionen der letzten Vorlesung I I 4 [28] Ähnliche Funktionen der letzten Vorlesung Pfade: c a t :: Path → Path → Path c a t Mt p = p c a t ( Cons p ps ) q s = Cons p ( c a t p s q s ) k a s s e :: E i n k a u f s w a g e n → I n t k a s s e LeererWagen = 0 k a s s e ( E i n k a u f a m e ) = c e n t a m+ k a s s e e r e v :: Path → Path r e v Mt = Mt r e v ( Cons p ps ) = c a t ( r e v ps ) ( Cons p Mt) i n v e n t u r :: L a g e r → I n t inventur LeeresLager = 0 i n v e n t u r ( L a g e r a m l ) = c e n t a m+ i n v e n t u r l Zeichenketten: l e n :: M y S t r i n g → I n t l e n Empty = 0 l e n ( Cons c s t r ) = 1+ l e n s t r c a t :: M y S t r i n g → M y S t r i n g → M y S t r i n g c a t Empty t = t c a t ( Cons c s ) t = Cons c ( c a t s t ) r e v :: M y S t r i n g → M y S t r i n g r e v Empty = Empty r e v ( Cons c t ) = c a t ( r e v t ) ( Cons c Empty ) I ein Fall pro Konstruktor I linearer rekursiver Aufruf 5 [28] Die Lösung: Polymorphie 6 [28] Parametrische Polymorphie: Typvariablen I Typvariablen abstrahieren über Typen data L i s t α = Empty | Cons α ( L i s t α) Definition (Polymorphie) Polymorphie ist Abstraktion über Typen Arten der Polymorphie I I Parametrische Polymorphie (Typvariablen): Generisch über alle Typen Ad-Hoc Polymorphie (Überladung): Nur für bestimmte Typen I α ist eine Typvariable I α kann mit Id oder Char instantiiert werden I List α ist ein polymorpher Datentyp I Typvariable α wird bei Anwendung instantiiert I Signatur der Konstruktoren Empty :: L i s t α Cons :: α→ L i s t α→ L i s t α 7 [28] 8 [28] Polymorphe Ausdrücke I I Polymorphe Funktionen Typkorrekte Terme: Typ Empty List α 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 I Parametrische Polymorphie für Funktionen: c a t :: L i s t α → L i s t α → L i s t α c a t Empty y s = ys c a t ( Cons x x s ) y s = Cons x ( c a t x s y s ) I Typvariable α wird bei Anwendung instantiiert: c a t ( Cons 3 Empty ) ( Cons 5 ( Cons 57 Empty ) ) c a t ( Cons ’ p ’ ( Cons ’ i ’ Empty ) ) ( Cons ’ 3 ’ Empty ) Nicht typ-korrekt: Cons ’a’ (Cons 0 Empty) aber nicht Cons True (Cons ’x’ Empty) c a t ( Cons True Empty ) ( Cons ’ a ’ ( Cons 0 Empty ) ) wegen Signatur des Konstruktors: I Typvariable: vergleichbar mit Funktionsparameter I Restriktion: Typvariable auf Resultatposition? Cons :: α→ L i s t α→ L i s t α 10 [28] 9 [28] Beispiel: Der Shop (refaktoriert) I Tupel Einkaufswagen und Lager als Listen: I Mehr als eine Typvariable möglich type L a g e r = [ ( A r t i k e l , Menge ) ] I Beispiel: Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β type E i n k a u f s w a g e n = [ ( A r t i k e l , Menge ) ] I I I I Gleicher Typ! Signatur des Konstruktors: Pair Bug or Feature? I Lösung: Datentyp verkapseln data L a g e r = L a g e r [ ( A r t i k e l , Menge ) ] d e r i v i n g ( Eq , Show ) data E i n k a u f s w a g e n = E i n k a u f s w a g e n [ ( A r t i k e l , Menge ) ] d e r i v i n g ( Eq , Show ) :: α→ β → P a i r α β Beispielterm Typ Pair 4 ’x’ Pair Int Char Pair (Cons True Empty) ’a’ Pair (List Bool) Char Pair (3+ 4) (Cons ’a’ Empty) Pair Int (List Char) Cons (Pair 7 ’x’) Empty List (Pair Int Char) 11 [28] Vordefinierte Datentypen: Tupel und Listen 12 [28] Vordefinierte Datentypen: Optionen I Eingebauter syntaktischer Zucker data P r e i s = Cent I n t | U n g u e l t i g I Tupel sind das kartesische Produkt data R e s u l t a t = Gefunden Menge | N i c h t g e f u n d e n data (α , β ) = (α , β ) data Trav = Succ Path | Fail I I (a, b) = alle Kombinationen von Werten aus a und b Instanzen eines vordefinierten Typen: I Auch n-Tupel: (a,b,c) etc. data Maybe α = J u s t α | N o t h i n g Listen Vordefinierten Funktionen (import Data.Maybe): data [ α ] = [ ] | α : [ α ] fromJust :: fromMaybe :: m ayb e T oL i st listToMaybe I Weitere Abkürzungen: [x]= x:[], [x,y] = x:y:[] etc. Maybe α → α α→ Maybe α→ α :: Maybe α→ [ α ] :: [ α ] → Maybe α −− “sicheres” head 13 [28] Übersicht: vordefinierte Funktionen auf Listen I ( ++ ) :: (!!) :: c o n c a t :: l e n g t h :: head , l a s t tail , init replicate take :: drop :: s p l i t A t :: r e v e r s e :: zip :: unzip :: and , o r :: sum :: p r o d u c t :: 14 [28] Vordefinierte Datentypen: Zeichenketten [α] → [α] → [α] −− Verketten [α] → Int → α −− n-tes Element selektieren [ [ α ] ] → [α] −− “flachklopfen” [α] → Int −− Länge :: [ α ] → α −− Erstes/letztes Element :: [ α ] → [ α ] −− Hinterer/vorderer Rest :: I n t → α→ [ α ] −− Erzeuge n Kopien Int → [α] → [α] −− Erste n Elemente Int → [α] → [α] −− Rest nach n Elementen I n t → [ α ] → ( [ α ] , [ α ] )−− Spaltet an Index n [α] → [α] −− Dreht Liste um [ α ] → [ β ] → [ ( α , β ) ] −− Erzeugt Liste v. Paaren [ ( α , β ) ] → ( [ α ] , [ β ] ) −− Spaltet Liste v. Paaren [ Bool ] → Bool −− Konjunktion/Disjunktion [ Int ] → Int −− Summe (überladen) [ Int ] → Int −− Produkt (überladen) 15 [28] I String sind Listen von Zeichen: type S t r i n g = [ Char ] I Alle vordefinierten Funktionen auf Listen verfügbar. I Syntaktischer Zucker zur Eingabe: " yoho " == [ ’ y ’ , ’ o ’ , ’ h ’ , ’ o ’ ] == ’ y ’ : ’ o ’ : ’ h ’ : ’ o ’ : [ ] I Beispiel: c n t :: Char → S t r i n g → I n t cnt c [ ] = 0 c n t c ( x : x s ) = i f ( c== x ) then 1+ c n t c x s else cnt c xs 16 [28] Zurück im Labyrinth Labyrinth verallgemeinert: Variadische Bäume I I Labyrinth als Instanz eines allgemeineren Datentyps? I Ja: variadische Bäume Variable Anzahl Kinderknoten: Liste von Kinderknoten data VTree α = Node α [ VTree α ] I Anzahl Knoten zählen: c o u n t :: VTree α→ I n t c o u n t ( VNode _ n s ) = 1+ c o u n t _ n o d e s n s data Lab = Node I d [ Lab ] type Path = [ I d ] c o u n t _ n o d e s :: [ VTree α ] → I n t count_nodes [ ] = 0 c o u n t _ n o d e s ( t : t s ) = c o u n t t+ c o u n t _ n o d e s t s type Trav = Maybe Path 18 [28] 17 [28] Ad-Hoc Polymorphie und Overloading Typklassen: Syntax I Definition (Überladung) c l a s s Show a where show :: a → S t r i n g Funktion f :: a→ b existiert für mehr als einen, aber nicht für alle Typen I Beispiel: I I Gleichheit: (==) :: a→ a→ Bool I Vergleich: (<) :: a→ a→ Bool I Anzeige: show :: a→ String I Lösung: Typklassen I Typklassen bestehen aus: I I Deklaration: Instantiierung: i n s t a n c e Show Bool where show True = " Wahr " show F a l s e = " F a l s c h " I Deklaration der Typklasse Instantiierung für bestimmte Typen Prominente vordefinierte Typklassen I Eq für (==) I Ord für (<) (und andere Vergleiche) I Show für show I Num (uvm) für numerische Operationen (Literale überladen) 19 [28] Typklassen in polymorphen Funktionen I Hierarchien von Typklassen Element einer Liste (vordefiniert): I elem :: Eq α ⇒ α→ [ α ] → Bool elem e [ ] = False elem e ( x : x s ) = e == x | | elem e x s I Typklassen können andere voraussetzen: class (<) (≤) a ≤ Sortierung einer List: qsort qsort I 20 [28] Eq α⇒ Ord :: α→ α→ :: α→ α→ b = a == b α where Bool Bool || a < b :: Ord α ⇒ [ α ] → [ α ] I Default-Definition von <= I Kann bei Instantiierung überschrieben werden Liste ordnen und anzeigen: s h o w s o r t e d :: ( Eq α , Show α) ⇒ [ α ] → S t r i n g s h o w s o r t e d x = show ( q s o r t x ) 21 [28] Polymorphie: the missing link 22 [28] Polymorphie in anderen Programmiersprachen: Java I Parametrisch Ad-Hoc Funktionen f :: α→ Int class F α where f :: a→ Int Typen data Maybe α= Just α | Nothing Konstruktorklassen I Kann Entscheidbarkeit der Typherleitung gefährden I Erstmal nicht relevant Polymorphie in Java: Methode auf alle Subklassen anwendbar I I Manuelle Typkonversion nötig, fehleranfällig Neu ab Java 1.5: Generics I Damit parametrische Polymorphie möglich c l a s s A b s L i s t<T> { p u b l i c A b s L i s t (T e l , A b s L i s t<T> t l ) { t h i s . elem= e l ; t h i s . n e x t= t l ; } p u b l i c T elem ; p u b l i c A b s L i s t<T> n e x t ; 23 [28] 24 [28] Polymorphie in anderen Programmiersprachen: Java Polymorphie in anderen Programmiersprachen: Java Typkorrekte Konkatenenation: v o i d c o n c a t ( A b s L i s t<T> o ) { A b s L i s t<T> c u r= t h i s ; w h i l e ( c u r . n e x t 6= n u l l ) c u r= c u r . n e x t ; c u r . n e x t= o ; } I Ad-Hoc Polymorphie: Interface und abstrakte Klassen I Flexibler in Java: beliebige Parameter etc. Nachteil: Benutzung umständlich, weil keine Typherleitung A b s L i s t<I n t e g e r> l= new A b s L i s t<I n t e g e r>( new I n t e g e r ( 1 ) , new A b s L i s t<I n t e g e r>( new I n t e g e r ( 2 ) , n u l l ) ) ; 25 [28] Polymorphie in anderen Programmiersprachen: C I Zusammenfassung “Polymorphie” in C: void * I struct l i s t { void ∗ head ; struct l i s t ∗ tail ; } I 26 [28] I Gegeben: int x = 7; s t r u c t l i s t s = { &x , NULL } ; I s.head hat Typ void *: int y ; y= ∗ ( i n t ∗ ) s . head ; I Nicht möglich: head direkt als Skalar (e.g. int) I C++: Templates Abstraktion über Typen I Uniforme Abstraktion: Typvariable, parametrische Polymorphie I Fallbasierte Abstraktion: Überladung, ad-hoc-Polymorphie In der Sprache: I Typklassen I polymorphe Funktionen und Datentypen I Vordefinierte Typen: Listen [a] und Tupel (a,b) I Nächste Woche: Abstraktion über Funktionen Funktionen höherer Ordnung 27 [28] 28 [28]