Praktische Informatik 3 (WS 2012/13) - informatik.uni

Werbung
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: Typvariablen und Polymorphie
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 =
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
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 ps ) 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 ps ) = 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 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
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
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
linearer rekursiver Aufruf
6 [28]
Die Lösung: Polymorphie
Definition (Polymorphie)
Polymorphie ist Abstraktion über Typen
Arten der Polymorphie
I
Parametrische Polymorphie (Typvariablen):
Generisch über alle Typen
I
Ad-Hoc Polymorphie (Überladung):
Nur für bestimmte Typen
7 [28]
Parametrische Polymorphie: Typvariablen
I
Typvariablen abstrahieren über Typen
data L i s t α = Empty
| Cons α ( L i s t α)
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 α
8 [28]
Polymorphe Ausdrücke
I
Typkorrekte Terme:
Typ
Empty
9 [28]
Polymorphe Ausdrücke
I
Typkorrekte Terme:
Typ
Empty
List α
9 [28]
Polymorphe Ausdrücke
I
Typkorrekte Terme:
Typ
Empty
List α
Cons 57 Empty
9 [28]
Polymorphe Ausdrücke
I
Typkorrekte Terme:
Typ
Empty
List α
Cons 57 Empty
List Int
9 [28]
Polymorphe Ausdrücke
I
Typkorrekte Terme:
Typ
Empty
List α
Cons 57 Empty
List Int
Cons 7 (Cons 8 Empty)
9 [28]
Polymorphe Ausdrücke
I
Typkorrekte Terme:
Typ
Empty
List α
Cons 57 Empty
List Int
Cons 7 (Cons 8 Empty)
List Int
9 [28]
Polymorphe Ausdrücke
I
Typkorrekte Terme:
Typ
Empty
List α
Cons 57 Empty
List Int
Cons 7 (Cons 8 Empty)
List Int
Cons ’p’ (Cons ’i’ (Cons ’3’ Empty))
9 [28]
Polymorphe Ausdrücke
I
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
9 [28]
Polymorphe Ausdrücke
I
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
9 [28]
Polymorphe Ausdrücke
I
I
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
Nicht typ-korrekt:
Cons ’a’ (Cons 0 Empty)
Cons True (Cons ’x’ Empty)
wegen Signatur des Konstruktors:
Cons :: α→ L i s t α→ L i s t α
9 [28]
Polymorphe Funktionen
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 )
aber nicht
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
Einkaufswagen und Lager als 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
Gleicher Typ!
I
Bug or Feature?
11 [28]
Beispiel: Der Shop (refaktoriert)
I
Einkaufswagen und Lager als 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
Gleicher Typ!
I
I
Bug or Feature?
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 )
11 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
:: α→ β → P a i r α β
12 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
I
:: α→ β → P a i r α β
Beispielterm
Typ
Pair 4 ’x’
12 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
I
:: α→ β → P a i r α β
Beispielterm
Typ
Pair 4 ’x’
Pair Int Char
12 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
I
:: α→ β → P a i r α β
Beispielterm
Typ
Pair 4 ’x’
Pair Int Char
Pair (Cons True Empty) ’a’
12 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
I
:: α→ β → P a i r α β
Beispielterm
Typ
Pair 4 ’x’
Pair Int Char
Pair (Cons True Empty) ’a’
Pair (List Bool) Char
12 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
I
:: α→ β → 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)
12 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
I
:: α→ β → 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)
12 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
I
:: α→ β → 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
12 [28]
Tupel
I
Mehr als eine Typvariable möglich
I
Beispiel: Tupel (kartesisches Produkt, Paare)
data P a i r α β = P a i r α β
I
Signatur des Konstruktors:
Pair
I
:: α→ β → 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)
12 [28]
Vordefinierte Datentypen: Tupel und Listen
I
Eingebauter syntaktischer Zucker
I
Tupel sind das kartesische Produkt
data (α , β ) = (α , β )
I
I
(a, b) = alle Kombinationen von Werten aus a und b
I
Auch n-Tupel: (a,b,c) etc.
Listen
data [ α ] = [ ] | α : [ α ]
I
Weitere Abkü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 = Gefunden Menge | N i c h t g e f u n d e n
data Trav = Succ Path
| Fail
Instanzen eines vordefinierten Typen:
data Maybe α = J u s t α | N o t h i n g
Vordefinierten Funktionen (import Data.Maybe):
fromJust
::
fromMaybe ::
m a yb e T oList
listToMaybe
Maybe α → α
α→ Maybe α→ α
:: Maybe α→ [ α ]
:: [ α ] → Maybe α
−− “sicheres” head
14 [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 ::
[α] → [α] → [α]
−− 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]
Vordefinierte Datentypen: Zeichenketten
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
I
Labyrinth als Instanz eines allgemeineren Datentyps?
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
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
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
18 [28]
Ad-Hoc Polymorphie und Overloading
Definition (Überladung)
Funktion f :: a→ b existiert für mehr als einen, aber nicht für alle Typen
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
Deklaration der Typklasse
I
Instantiierung fü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 Bool where
show True = " Wahr "
show F a l s e = " F a l s c h "
I
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)
20 [28]
Typklassen in polymorphen Funktionen
I
Element einer Liste (vordefiniert):
elem :: Eq α ⇒ α→ [ α ] → Bool
elem e [ ]
= False
elem e ( x : x s ) = e == x | | elem e x s
I
Sortierung einer List: qsort
qsort
I
:: Ord α ⇒ [ α ] → [ α ]
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 andere voraussetzen:
class
(<)
(≤)
a ≤
Eq α⇒ Ord
:: α→ α→
:: α→ α→
b = a == b
α where
Bool
Bool
|| 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
data Maybe α=
Just α | Nothing
23 [28]
Polymorphie: the missing link
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
23 [28]
Polymorphie in anderen Programmiersprachen: Java
I
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 ;
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 und abstrakte Klassen
I
Flexibler in Java: beliebige Parameter etc.
26 [28]
Polymorphie in anderen Programmiersprachen: C
I
“Polymorphie” in C: void *
struct l i s t {
void
∗ head ;
struct l i s t ∗ tail ;
}
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
27 [28]
Zusammenfassung
I
I
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
28 [28]
Herunterladen