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 1 [28]
Fahrplan
I 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
2 [28]
Inhalt
I Letzte Vorlesung: rekursive Datentypen
I Diese Vorlesung:
I Abstraktionüber Typen:TypvariablenundPolymorphie
I Arten der Polymorphie:
I Parametrische Polymorphie
I Ad-hoc Polymorphie
3 [28]
Ähnliche Datentypen der letzten Vorlesung
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 =
L e e r e r W a g e n
| 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 einkonstanter Konstruktor
I einlinear rekursiverKonstruktor
4 [28]
Ähnliche Funktionen der letzten Vorlesung
I Pfade:
c a t :: Path→ Path→ Path c a t Mt p = p
c a t ( Cons p p s ) q s = Cons p ( c a t p s q s ) r e v :: Path→ Path
r e v Mt = Mt
r e v ( Cons p p s ) = c a t ( r e v p s ) ( Cons p Mt )
I Zeichenketten:
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 )
5 [28]
Ähnliche Funktionen der letzten Vorlesung
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 L e e r e r W a g e n = 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 i n v e n t u r :: L a g e r→ I n t
i n v e n t u r L e e r e s L a g e r = 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 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
I ein Fall pro Konstruktor
I linearerrekursiver Aufruf
6 [28]
Die Lösung: Polymorphie
Definition (Polymorphie)
Polymorphie istAbstraktion über Typen
Arten der Polymorphie
I ParametrischePolymorphie (Typvariablen):
Generisch überalleTypen
I Ad-HocPolymorphie (Überladung):
Nur fürbestimmte Typen
7 [28]
Parametrische Polymorphie: Typvariablen
I Typvariablenabstrahieren über Typen data L i s t α = Empty
| Cons α ( L i s t α)
I α ist eineTypvariable
I α kann mitIdoder Charinstantiiert werden
I List α ist ein polymorpherDatentyp
I Typvariableα wird bei Anwendung instantiiert
I Signaturder Konstruktoren Empty :: L i s t α
Cons :: α→ L i s t α→ L i s t α
8 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt: Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors: Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Ausdrücke
I TypkorrekteTerme: 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 Nichttyp-korrekt:
Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignatur des Konstruktors:
Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Funktionen
I Parametrische Polymorphie fürFunktionen:
c a t :: L i s t α → L i s t α → L i s t α
c a t Empty y s = y s
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 ) abernicht
c a t ( Cons True Empty ) ( Cons ’ a ’ ( Cons 0 Empty ) )
I Typvariable: vergleichbar mit Funktionsparameter
I Restriktion: Typvariable auf Resultatposition?
10 [28]
Beispiel: Der Shop (refaktoriert)
I Einkaufswagenund Lagerals Listen:
type L a g e r = [ ( A r t i k e l , Menge ) ]
type E i n k a u f s w a g e n = [ ( A r t i k e l , Menge ) ]
I GleicherTyp!
I Bug or Feature?
I Lösung: Datentypverkapseln
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 )
11 [28]
Beispiel: Der Shop (refaktoriert)
I Einkaufswagenund Lagerals Listen:
type L a g e r = [ ( A r t i k e l , Menge ) ]
type E i n k a u f s w a g e n = [ ( A r t i k e l , Menge ) ]
I GleicherTyp!
I Bug or Feature?
I Lösung: Datentypverkapseln
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 )
11 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Tupel
I Mehr alseineTypvariable möglich
I Beispiel:Tupel (kartesisches Produkt, Paare) data P a i r α β = P a i r α β
I Signatur des Konstruktors:
P a i r :: α→ β→ P a i r α β
I 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)
12 [28]
Vordefinierte Datentypen: Tupel und Listen
I Eingebautersyntaktischer Zucker
I Tupelsind das kartesische Produkt data (α, β) = (α, β)
I (a, b)=alle Kombinationenvon Werten ausaundb
I Auch n-Tupel:(a,b,c) etc.
I Listen
data [α] = [ ] | α : [α]
I WeitereAbkürzungen:[x]= x:[],[x,y] = x:y:[]etc.
13 [28]
Vordefinierte Datentypen: Optionen
data P r e i s = Cent I n t | U n g u e l t i g
data R e s u l t a t = G e f u n d e n Menge | N i c h t g e f u n d e n data Trav = Succ Path
| F a i l
Instanzen eines vordefiniertenTypen:
data Maybe α = J u s t α | N o t h i n g Vordefinierten Funktionen (import Data.Maybe):
f r o m J u s t :: Maybe α → α
fromMaybe :: α→ Maybe α→ α
m a y b e T o L i s t :: Maybe α→ [α]
l i s t T o M a y b e :: [α]→ Maybe α −−“sicheres” head
14 [28]
Übersicht: vordefinierte Funktionen auf Listen I
(++) :: [α]→ [α]→ [α] −−Verketten
( ! ! ) :: [α]→ I n t→ α −−n-tes Element selektieren c o n c a t :: [ [α] ]→ [α] −−“flachklopfen”
l e n g t h :: [α]→ I n t −−Länge
head , l a s t :: [α]→ α −−Erstes/letztes Element t a i l , i n i t :: [α]→ [α] −−Hinterer/vorderer Rest r e p l i c a t e :: I n t→ α→ [α] −−Erzeugen Kopien t a k e :: I n t→ [α]→ [α] −−Erste n Elemente d r o p :: I n t→ [α]→ [α] −−Rest nachn Elementen s p l i t A t :: I n t→ [α]→ ( [α] , [α] )−−Spaltet an Indexn r e v e r s e :: [α]→ [α] −−Dreht Liste um
z i p :: [α]→ [β]→ [ (α, β) ] −−Erzeugt Liste v. Paaren u n z i p :: [ (α, β) ]→ ( [α] , [β] ) −−Spaltet Liste v. Paaren and , o r :: [ B o o l ]→ B o o l −−Konjunktion/Disjunktion
sum :: [ I n t ]→ I n t −−Summe (überladen)
p r o d u c t :: [ I n t ]→ I n t −−Produkt (überladen)
15 [28]
Vordefinierte Datentypen: Zeichenketten
I Stringsind Listen von Zeichen:
type S t r i n g = [ Char ]
I Alle vordefiniertenFunktionen auf Listenverfügbar.
I Syntaktischer Zuckerzur 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
c n t c [ ] = 0
c n t c ( x : x s ) = i f ( c== x ) then 1+ c n t c x s e l s e c n t c x s
16 [28]
Zurück im Labyrinth
I Labyrinth als Instanz eines allgemeineren Datentyps?
I Ja:variadische Bäume
data Lab = Node I d [ Lab ] type Path = [ I d ]
type Trav = Maybe Path
17 [28]
Zurück im Labyrinth
I Labyrinth als Instanz eines allgemeineren Datentyps?
I Ja:variadische Bäume
data Lab = Node I d [ Lab ] type Path = [ I d ]
type Trav = Maybe Path
17 [28]
Labyrinth verallgemeinert: Variadische Bäume
I VariableAnzahl 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
c o u n t _ n o d e s :: [ VTree α] → I n t c o u n t _ n o d e s [ ] = 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
18 [28]
Ad-Hoc Polymorphie und Overloading
Definition (Überladung)
Funktion f:: a→ b existiert fürmehr als einen, abernichtfür alleTypen
I
I Beispiel:
I Gleichheit:(==)::a→a→Bool
I Vergleich:(<) :: a→a→Bool
I Anzeige:show :: a→ String
I Lösung:Typklassen
I Typklassen bestehen aus:
I Deklarationder Typklasse
I Instantiierungfür bestimmte Typen
19 [28]
Typklassen: Syntax
I Deklaration:
c l a s s Show a where show :: a→ S t r i n g
I Instantiierung:
i n s t a n c e Show B o o l where show True = " Wahr "
show F a l s e = " F a l s c h "
I Prominente vordefinierte Typklassen
I Eqfür (==)
I Ordfür(<)(und andere Vergleiche)
I Showfür show
I Num(uvm) für numerische Operationen (Literale überladen)
20 [28]
Typklassen in polymorphen Funktionen
I Element einer Liste (vordefiniert):
e l e m :: Eq α ⇒ α→ [α]→ B o o l e l e m e [ ] = F a l s e
e l e m e ( x : x s ) = e == x | | e l e m e x s
I Sortierung einer List:qsort
q s o r t :: Ord α ⇒ [α]→ [α]
I 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]
Hierarchien von Typklassen
I Typklassen können anderevoraussetzen:
c l a s s Eq α⇒ Ord α where (<) :: α→ α→ B o o l (≤) :: α→ α→ B o o l a ≤ b = a == b | | a < b
I Default-Definition von<=
I Kann bei Instantiierung überschrieben werden
22 [28]
Polymorphie: the missing link
Parametrisch Ad-Hoc
Funktionen f :: α→Int class F αwhere
f :: a→ Int
Typen dataMaybe α=
Just α | Nothing
Konstruktorklassen
I KannEntscheidbarkeitder Typherleitung gefährden
I Erstmalnicht relevant
23 [28]
Polymorphie: the missing link
Parametrisch Ad-Hoc
Funktionen f :: α→Int class F αwhere
f :: a→ Int
Typen dataMaybe α=
Just α | Nothing
Konstruktorklassen
I KannEntscheidbarkeitder Typherleitung gefährden
I Erstmalnicht relevant
23 [28]
Polymorphie in anderen Programmiersprachen: Java
I Polymorphie inJava: Methode auf alle Subklassen anwendbar
I ManuelleTypkonversionnötig, fehleranfällig
I Neu ab Java 1.5:Generics
I Damitparametrische Polymorphiemö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 . e l e m= e l ;
t h i s . n e x t= t l ; }
p u b l i c T e l e m ;
p u b l i c A b s L i s t<T> n e x t ;
24 [28]
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 ;
}
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: Java
I Ad-Hoc Polymorphie:Interface undabstrakte Klassen
I Flexibler in Java: beliebige Parameter etc.
26 [28]
Polymorphie in anderen Programmiersprachen: C
I “Polymorphie” in C:void * s t r u c t l i s t {
v o i d ∗he ad ; s t r u c t l i s t ∗t a i l ; }
I Gegeben:
i n t x = 7 ;
s t r u c t l i s t s = { &x , NULL } ;
I s.headhat Typ void *:
i n t y ;
y= ∗( i n t ∗) s . hea d ;
I Nicht möglich:head direkt als Skalar (e.g.int)
I C++:Templates
27 [28]
Zusammenfassung
I Abstraktionüber Typen
I UniformeAbstraktion: Typvariable, parametrische Polymorphie
I FallbasierteAbstraktion: Überladung, ad-hoc-Polymorphie
I 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
28 [28]