Praktische Informatik 3: Einführung in die Funktionale Programmierung
Vorlesung vom 10.11.2010: Rekursive Datentypen
Christoph Lüth & Dennis Walter Universität Bremen Wintersemester 2010/11
Rev. 1152 1 [23]
Fahrplan
I Teil I: Funktionale Programmierung im Kleinen
IEinführung
IFunktionen und Datentypen
IRekursive Datentypen
ITypvariablen und Polymorphie
IFunktionen höherer Ordnung
ITypinferenz
I Teil II: Funktionale Programmierung im Großen I Teil III: Funktionale Programmierung im richtigen Leben
2 [23]
Inhalt
IRekursiveDatentypen
IFormen der Rekursion
IRekursiveDefinition
IRekursive Datentypen in anderen Sprachen
IInduktiverBeweis
ISchluss vomkleinerenaufsgrößere
3 [23]
Der Allgemeine Fall: Algebraische Datentypen
Definition einesalgebraischen DatentypenT:
data T= C1t1,1. . .t1,k1
. . .
| Cntn,1. . .tn,kn I KonstruktorenC1, . . . ,Cnsinddisjunkt:
Cix1. . .xn=Cjy1. . .ym−→i=j
I Konstruktorensindinjektiv:
C x1. . .xn=C y1. . .yn−→xi=yi I Konstruktorenerzeugenden Datentyp:
∀x∈T.x=Ciy1. . .ym Diese Eigenschaften machenFallunterscheidungmöglich.
4 [23]
Rekursive Datentypen
IDer definierte TypTkannrechtsbenutzt werden.
IRekursive Datentypen sindunendlich
IEntsprichtinduktiver Definition
5 [23]
Induktive Definitionen
I Beispielnatürliche Zahlen: Peano-Axiome
I0∈N
Iwennn∈N, dannS n∈N
ISinjektivundS n6=0
IInduktionsprinzip:φ(0),φ(x)−→φ(S x), dann∀n∈N.φ(n)
I Induktionsprinzip erlaubt Definitionrekursiver Funktionen:
n+0 = n n+S m = S(n+m)
6 [23]
Natürliche Zahlen in Haskell
IDirekte Übersetzung der Peano-Axiome IDerDatentyp:
data Nat = Z e r o
| S Nat
IRekursiveFunktionsdefinition:
add :: Nat→ Nat→ Nat add n Z e r o = n
add n ( S m) =S ( add n m)
7 [23]
Beispiel: Zeichenketten selbstgemacht
I EineZeichenketteist
Ientwederleer(das leere Wort)
Ioder einZeichencund eine weitereZeichenkettexs data M y S t r i n g =Empty
| Cons Char M y S t r i n g
I LineareRekursion
IGenau ein rekursiver Aufruf
8 [23]
Rekursive Definition
ITypisches Muster:Fallunterscheidung
IEinFallproKonstruktor
IHier:
ILeereZeichenkette
INichtleereZeichenkette
9 [23]
Funktionen auf Zeichenketten
I Länge:
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 Verkettung:
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 )
I Umkehrung:
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 )
10 [23]
Baumartige Rekursion: Binäre Bäume
IDatentyp:
data BTree = MtBTree
| BNode I n t BTree BTree
IFunktion, bsp. Höhe:
h e i g h t :: BTree→ I n t h e i g h t MtBTree =0
h e i g h t ( BNode j l r ) = max ( h e i g h t l ) ( h e i g h t r )+1
IBaumartigeRekursion
IDoppelter rekursiver Aufruf
11 [23]
Wechselseitige Rekursion: Variadische Bäume
I VariableAnzahl Kinderknoten data VTree = MtVTree
| VNode S t r i n g VNodes
data VNodes =MtVNodes
| VMore VTree VNodes
I VNodes:Listevon Kinderbäumen
12 [23]
Wechselseitige Rekursion: Variadische Bäume
IHauptfunktion:
c o u n t :: VTree→ I n t c o u n t MtVTree = 0
c o u n t ( VNode _ n s ) = 1+ c o u n t _ n o d e s n s
IHilfsfunktion:
c o u n t _ n o d e s :: VNodes → I n t c o u n t _ n o d e s MtVNodes = 0
c o u n t _ n o d e s ( VMore t n s )= c o u n t t+ c o u n t _ n o d e s n s
13 [23]
Rekursive Typen in anderen Sprachen
I Standard ML: gleich
I Lisp: keine Typen, aber alles ist eine S-Expression data SExpr = Quote Atom | Cons SExpr SExpr
I Python,Ruby:
IListen (Sequenzen) vordefiniert
IKeine anderen Typen
14 [23]
Rekursive Typen in Java
INachbildung durch Klassen, z.B. für Listen:
c l a s s L i s t {
p u b l i c L i s t ( O b j e c t e l , L i s 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 O b j e c t e l e m ; p u b l i c L i s t n e x t ; ILänge (iterativ):
i n t l e n g t h ( ) { i n t i= 0 ;
f o r ( L i s t c u r= t h i s; c u r 6= n u l l; c u r= c u r . n e x t ) i++;
r e t u r n i ; }
15 [23]
Rekursive Typen in C
I C: Produkte, Aufzählungen, keine rekursiven Typen I Rekursion durchZeiger
t y p e d e f s t r u c t l i s t _ t {
v o i d ∗e l e m ;
s t r u c t l i s t _ t ∗n e x t ; } ∗l i s t ;
I Konstruktorennutzerimplementiert l i s t c o n s (v o i d ∗hd , l i s t t l ) { l i s t l ;
i f ( ( l= ( l i s t ) m a l l o c (s i z e o f(s t r u c t l i s t _ t ) ) )== NULL ) { p r i n t f ( " Out o f memory \n " ) ; e x i t (−1 ) ;
}
l→ e l e m= hd ; l→ n e x t= t l ; r e t u r n l ;
}
16 [23]
Rekursive Definition, induktiver Beweis
IDefinition durchRekursion
IBasisfall (leere Zeichenkette)
IRekursion (nicht-leere Zeichenkette) 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 )
IReduktion der Eingabe (vom größeren aufs kleinere) IBeweisdurch Induktion
ISchluß vom kleineren aufs größere
17 [23]
Beweis durch vollständige Induktion
Zu zeigen:
Für alle natürlichen ZahlenxgiltP(x).
Beweis:
I Induktionsbasis:P(0) I Induktionsschritt:
IInduktionsvoraussetzungP(x)
Izu zeigenP(x+1)
18 [23]
Beweis durch strukturelle Induktion (Zeichenketten)
Zu zeigen:
Für alle (endlichen) ZeichenkettenxsgiltP(xs) Beweis:
IInduktionsbasis:P() IInduktionsschritt:
IInduktionsvoraussetzungP(xs)
Izu zeigenP(x xs)
19 [23]
Beweis durch strukturelle Induktion (Allgemein)
Zu zeigen:
Für allexinT giltP(x) Beweis:
I Für jeden KonstruktorCi:
IVoraussetzung: für alleti,jgiltP(ti,j)
Izu zeigenP(Citi,1. . .ti,ki)
20 [23]
Beispielbeweise
lens ≥ 0 (1)
len(cats t) = lens+lent (2)
len(revs) = lens (3)
21 [23]
Spezifikation und Korrektheit
I Die erstennZeichen einer Zeichenkette (n≥0) takeN :: I n t→ M y S t r i n g→ M y S t r i n g takeN n Empty =Empty
takeN n ( Cons c s ) = i f n == 0 then Empty e l s e Cons c ( takeN ( n−1) s ) I Zeichenkette ohne die erstennZeichen (n≥0)
dropN :: I n t→ M y S t r i n g→ M y S t r i n g
dropN n Empty =Empty
dropN n ( Cons c s ) = i f n == 0 then Cons c s e l s e dropN ( n− 1 ) s I Eigenschaften:
len(takeNn s) ≤ n (4)
len(dropNn s) ≥ lens−n (5) cat(takeNn s) (dropNn s) = s (6)
22 [23]
Zusammenfassung
IDatentypen könnenrekursivsein
IRekursive Datentypen sindunendlich(induktiv) IFunktionen werdenrekursivdefiniert
IFormender Rekursion: linear, baumartig, wechselseitig IRekursiveDefinition ermöglichtinduktivenBeweis INächsteWoche: Abstraktion über Typen (Polymorphie)
23 [23]