Listen in Haskell: Primitive Rekursion über Listen Primitive

Werbung
Listen in Haskell:
Primitive Rekursion über Listen
• Listen . . . Zusammenfassung beliebig vieler Elemente vom selben Typ
• auch ‘tail recursion’ genannt
• Darstellung des Listentyp: [<typ>], z.B.
• Definition durch
– Angabe des Ausgangswerts für [] und
– Angabe, wie von Wert für xs auf Wert von (x:xs) übergegangen wird
[Int], [Char], [[Int]], [(Name, Matrnr)], ...
• Listen werden – sofern ungleich der leeren Liste [] - durch Anwendung
des Konstruktors ‘:’ in eindeutiger Weise ausgehend von [] aufgebaut
• Beispiel:
length []
= 0
length (x:xs) = 1 + length xs
• Beispiel: [4, 2, 3] == 4:2:3:[] == 4:(2:(3:[]))
• ‘:’ ist rechts-assoziativ, d.h. x:y:zs = x:(y:zs)
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 45
Primitive Rekursion über Listen
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 46
Rekursion über Listen cont.
Beachte:
• Beispiel: Summe der Werte der Listenelemente
• length ist polymorph, d.h. auf Listen unterschiedlichen Typs anwendbar:
length :: [a] -> Int
• ’wildcard’ in der zweiten Gleichung der Definition möglich, d.h.
length ( :xs) = 1 + length xs
sum :: [Int] -> Int
sum []
= 0
sum (x:xs) = x + sum xs
• Frage: sum [2, 4 .. 11] ֒→ . . . ?
• length ist wie viele andere Funktionen auf Listen im sog. StandardPrelude von Haskell bereits vordefiniert
• sum ist vordefiniert und polymorph
Prelude> :t sum
sum :: Num a => [a] -> a
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 47
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 48
Rekursion über Listen cont.
Der Typ String
Beispiel: Sortieren mit Insertion-Sort
• Spezialfall: Liste aus Zeichen, d.h. type String = [Char]
iSort :: [Int] -> [Int]
• alle polymorphen Listenfunktionen können für String benutzt werden
iSort []
iSort (x:xs)
= []
= ins x (iSort xs)
• Ausgabe mit putStr
putStr :: String -> IO ()
ins :: Int -> [Int] -> [Int]
ins
ins
|
|
• Wechsel zwischen Strings und Werten:
show (2 + 3) ==> "5"
x []
= [x]
x (y:ys)
x<= y
= x:(y:ys)
otherwise = y: ins x ys
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), • umgekehrt:
(read "True") :: Bool ==> True
49
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 50
Darstellung von Listen
Darstellung von Listen
• für Listen von Zahlen, Zeichen und anderen Aufzählungstypen gibt es
Kurzschreibweisen
• Variante: die ‘Differenz’ zwischen dem zweiten und dem ersten Element
ergibt die ‘Schrittweite’
• [n .. m] Kurzform für [n,n+1,...,m]
(falls m kleiner als n ist Liste leer)
• Beispiele:
[3,5 .. 14]
[0.0,0.4 .. 2.0]
[’f’,’h’ .. ’q’]
• Beispiele:
[3 .. 9]
[1.2 .. 4.1]
[’f’ .. ’q’]
= [3,5,7,9,11,13]
= [0.0,0.4,0.8,1.2,1.6,2.0]
= "fhjlnp"
== [3,4,5,6,7,8,9]
== [1.2,2.2,3.2]
== "fghijklmnopq"
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 51
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 52
Listenkomprehension
Listenkomprehension cont.: Beispiele
(vgl. [S.Thompson, 1999, pp.79])
• Vorbild: math. Notation für Mengen
• Beispiel: Teiler(n) = {i∈Nk i≤n, i Teiler von n}
• Sei ex die Liste [2,4,7]
• in Haskell:
teiler :: Int -> [Int]
teiler n = [ i | i<-[1..n], mod n i == 0]
• [ 2*n | n<-ex] ֒→ [4,8,14]
• lies: ‘Nimm alle 2*n für n aus der Liste ex’
– Liste [1..n] wirkt als Generator
– Test mod n i == 0 wählt Elemente aus
• zur Veranschaulichung: Auswertung tabellarisch
n
2*n
• mehrere Tests in Form boolescher Ausdrücke möglich
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 53
=
=
2
4
4
8
7
14
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), Listenkomprehension cont.: Beispiele
54
Listenkomprehension cont.: Beispiele
(vgl. [S.Thompson, 1999, pp.79])
(vgl. [S.Thompson, 1999, pp.79])
• Sei isEven definiert:
• links von <- können nicht nur Variable, sondern auch Muster (pattern)
stehen
isEven :: Int -> Bool
isEven n = (n ‘mod‘ 2 == 0)
• Beispiel: addPairs :: [(Int,Int)] -> [Int]
addPairs pairList = [ n+m | (n,m) <- pairList]
• [ isEven n | n<-ex] ֒→ [True, True, False]
• Veranschaulichung mit Tabelle:
• mehrere Tests möglich
[ n+m
n
m
n+m
• [ 2*n | n<-ex, isEven n, n>3]
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 55
| (n,m) <- [(2,3),(2,1),(7,8)]]
=
2
2
7
=
3
1
8
=
5
3
15
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 56
Listenkomprehension cont.
Listenkomprehension cont.:
(vgl. [S.Thompson, 1999, pp.79])
• Syntax: allgemeine Form ist [ e | q1, ... qk ]
• zusätzlicher Test:
• dabei ist jeder der Qualifikatoren qi
• nur geordnete Paare addieren
addOrdPairs :: [(Int,Int)] -> [Int]
addOrdPairs pairList = [ n+m | (n,m) <- pairList, n < m]
• wichtig: ein Ausdruck lExp bzw. bExp in qi kann auf die in q1 bis qi−1
benutzten Variablen verweisen
• Frage: addOrdPairs [(2,3),(2,1),(7,8)] ֒→ . . . ?
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), – entweder ein Generator der Form p <- lExp mit p Muster und lExp
Ausdruck vom Listentyp
– oder ein Test, d.h. boolescher Ausdruck bExp
57
Listenkomprehension cont.
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), Listenkomprehension cont.:
(vgl. [S.Thompson, 1999, 17.3])
• pythagoräische Tripel: für welche Tripel (x, y, z) ganzer Zahlen gilt:
• mit mehreren Generatoren können Elemente aus zwei oder mehr Listen
kombiniert werden
x2 + y2 = z2 ?
• als Listenkomprehension:
• Beispiel:
pyTriple n = [(x,y,z)| x<-[2 .. n], y<-[x+1 .. n],
z<-[y+1 .. n], x*x+y*y==z*z]
pairs :: [a] -> [b] -> [(a,b)]
pairs xs ys = [ (x,y) | x<-xs , y<-ys ]
• Frage:
pyTriple 100 ֒→ ... ?
pairs [1,2,3] [4,5]
֒→ [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 58
59
c Prof. Dr. D. Rösner; erstellt: 5. April 2007
Sommer 2007, Programmierparadigmen (PGP), 60
Herunterladen