V3 ALP1 Tupel List 2013 - inf.fu-berlin.de · absC ( real, img ) = sqrt( real*real + img*img )...

47
ALP I Funktionale Programmierung Zusammengesetzte Datentypen in Haskell Prof. Dr. Margarita Esponda WS 2012/2013 Prof. Dr. Margarita Esponda Funktionale Programmierung

Transcript of V3 ALP1 Tupel List 2013 - inf.fu-berlin.de · absC ( real, img ) = sqrt( real*real + img*img )...

ALP IFunktionale Programmierung

Zusammengesetzte Datentypen in Haskell

Prof. Dr. Margarita Esponda

WS 2012/2013

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Zusammengesetzte Datentypen

Tupel

List

String

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Zusammengesetzte Datentypen

Ein Tupel ist eine Ansammlung von zwei oder mehreren

Daten, die unterschiedliche Datentypen besitzen können.

Tupel-Datentyp

Beispiele:

( "Peter" , "Meyer", 439990 ) :: ( String, String, Int )

Mit Hilfe von Tupeln können zusammengehörige Daten als

Einheit behandelt werden.

( 2.5, 3.0 ) :: ( Double, Double )

Studierende

Punkt

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Tupel-Typ

Funktionsdefinition mit Tupeln:

distance :: (Double, Double) -> (Double, Double) -> Double

distance (x1,y1) (x2,y2) = sqrt (squareX + squareY )

where

squareX = (x1-x2) * (x1-x2)

squareY = (y1-y2) * (y1-y2)

Prof. Dr. Margarita Esponda

Funktionale Programmierung

rgbColor :: (Int, Int, Int) → [Char]

rgbColor (red, green, blue) = case (red, green, blue) of

(0,0,0) → "black"

(255,255,255) → "white"

(255,0,0) → "red"

(0,255,0) → "green"

(0,0,255) → "blue"

otherwise → "other color"

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Tupel-Datentyp

Tupel-TypEin Tupel-Typ hat folgende allgemeine Form:

( t1 , t2 , … , tn ), wobei t1 , t2 , … , tn beliebige

Datentypen sind

Zwei einfache Funktionen für Tupel sind:

fst (x, y) = x

snd (x, y) = y

Die erwartete Tupel-Struktur wird in den Argumenten sichtbar

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Tupel-Typ

Funktionsdefinition mit Tupeln:

distance :: (Double, Double) -> (Double, Double) -> Double

distance p1 p2 = sqrt(xd^2 + yd^2)

where

xd = (fst p1) - (fst p2)

yd = (snd p1) - (snd p2)

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Pattern-Matching

oder0 :: Bool -> Bool -> Bool

oder0 False False = False

oder0 False True = True

oder0 True False = True

oder0 True True = True

oder :: Bool -> Bool -> Bool

oder False False = False

oder x y = True

und :: Bool -> Bool -> Bool

und True True = True

und _ _ = False

beliebige Argumente vom Typ Bool

myNot :: Bool -> Bool

myNot True = False

myNot False = True

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Pattern-Matching

In Haskell ist es möglich durch Pattern-Matching eine Auswahl

verschiedener Funktionsgleichungen zu definieren.

Allgemeine Form:

f p11 p12 … p1n = e1

f p21 p22 … p2n = e2

…..f pk1 pk2 … pkn = ek

Die pij Muster werden von oben nach unten und von links nach

rechts geprüft.

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Typ-SynonymeTyp-Synonyme werden verwendet, um die Lesbarkeit von

Programmen mit Hilfe von aussagekräftigen Typ-Namen zu

verbessern.

Allgemeine Form:

type Typname = …….

Beispiele:type Student = (String, String, Int)

type Point = (Double, Double)

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Typ-Synonyme

Funktionsdefinition mit Typ-Synomyme:

type Point = (Double, Double)

distance :: Point -> Point -> Double

distance (x1,y1) (x2,y2) = sqrt (sumSq (x1-x2) (y1-y2))

where

sumSq x y = x*x + y*y

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Typ-Synonyme

Text

type Complex = (Double, Double)

realPart :: Complex -> DoublerealPart ( real, img ) = real

imgPart :: Complex -> DoubleimgPart ( real, img ) = img

sumC :: Complex -> Complex -> ComplexsumC (r1,i1) (r2,i2) = (r1+r2, i1+i2)

absC :: Complex -> DoubleabsC ( real, img ) = sqrt( real*real + img*img )

Prof. Dr. Margarita Esponda

Funktionale Programmierung

13

Rekursion ist ein fundamentales Konzept in der Mathematik

Rekursion ist ein fundamentales Konzept in der Informatik

- eine Denkform für Problembeschreibung

- eine Methode zur Problemlösung

- enge Beziehung zur mathematischen Induktion

Rekursion

Rekursive Funktionsdefinitionen sind die wichtigste

Programmiertechnik in funktionalen Programmiersprachen.

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Rekursive Funktionen

factorial :: Int -> Int

factorial n = if n==0

then 1

else n * factorial (n-1)

Typisches Beispiel: Die Fakultätsfunktion

Wie viele Permutationen kann eine Reihe von Objekten maximal haben?

Prof. Dr. Margarita Esponda

Funktionale Programmierung

factorial :: Int -> Int

factorial n | n==0 = 1

| otherwise = n*factorial (n-1)

factorial :: Integer -> Integer

factorial n | n==0 = 1

| True = n*factorial (n-1)

richtig aber nicht schön

Rekursive Funktionen

factorial :: Int -> Int

factorial 0 = 1

factorial n = n * factorial (n-1)

bigFactorial :: Integer -> Integer

bigFactorial 0 = 1

bigFactorial n = n * bigFactorial (n-1)

Die Fakultätsfunktion

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Pattern-Matching

Rekursive Funktionen

factorial :: Int -> Int

factorial n = n * factorial (n-1)

factorial 0 = 1

Die Fakultätsfunktion

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Pattern-Matching

Warning: Pattern match(es) are overlapped In the definition of `factorial': factorial 0 = ...Ok, modules loaded:

factorial 0 *** Exception: stack overflow

Rekursive Funktionen

ggt :: Integer → Integer → Integer

ggt p q | p>q = ggt (p-q) q

| p==q = p

| p<q = ggt p (q-p)

noch ein Klassiker:

Größter gemeinsamer Teiler von zwei natürlichen Zahlen a, b

Euklid (originaler Algorithmus)

Probleme?

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Rekursive Funktionen

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Probleme?

ggt 20 8 ⇒ (20-8) 8

⇒ ggt 12 8

⇒ ggt (12-8) 8

⇒ ggt 8 4

⇒ ggt 4 4

⇒ 4

ggt 8 0 ⇒ ggt (8-0) 0 ⇒ ggt 8 0 ⇒ ggt 8 0

.... :(

ggt :: Integer → Integer → Integer

ggt p q | p>q = ggt (p-q) q | p==q = p | p<q = ggt p (q-p)

Rekursive Funktionen

1. Lösung:ggt a b

| b == 0 = a

| otherwise = ggt b (a `mod` b)

Prof. Dr. Margarita Esponda

Funktionale Programmierung

2. Lösung:ggt a b

| a == 0 && b == 0 = ???

| b == 0 = a

| otherwise = ggt b (a `mod` b)

Pizzaproblem (Jakob Steiner, 1826)

Wie viele Pizza-Teile entstehen maximal, wenn eine Pizza mit n geraden Schnitten aufgeteilt wird?

maxSurfaces :: Int -> IntmaxSurfaces 0 = 1maxSurfaces n = maxSurfaces (n - 1) + n

Prof. Dr. Margarita Esponda

Funktionale Programmierung

ab=a + ba

Rekursive Funktionen

Zwei positive reelle Zahlen stehen im Verhältnis der goldenen Zahl, wennBerechnung des goldenen Schnitts

gilt, mit a > b > 0.

goldenRatio :: Int -> DoublegoldenRatio n | n == 0 = 1 | n > 0 = 1 + 1 / goldenRatio (n-1) | otherwise = error "not defined for negative numbers"

Φ = 1+ 1Φ

Goldener Schnitt =

Prof. Dr. Margarita Esponda

Funktionale Programmierung

22

Fibonacci-ZahlenProblem:

Zu Beginn eines Jahres gibt es genau ein Paar neugeborener Kaninchen.

Ein Paar neugeborener Kaninchen ist erst nach einem Monat fortpflanzungsfähig, sodass erst nach zwei Monaten ein neues Kaninchenpaar zur Welt gebracht werden kann.

Jedes nicht neugeborene Kaninchen bekommt ein neues Kaninchenpaar monatlich.

Wie viele Kaninchen gibt es nach einem Jahr, wenn keines der Kaninchen stirbt?

Prof. Dr. Margarita Esponda

Funktionale Programmierung

23

Fibonacci-Zahlen 1

1

2

3

5

8

Prof. Dr. Margarita Esponda

Funktionale Programmierung

24

Fibonacci-ZahlenDer Stammbaum einer Drohne

8

13

Drohne

1Mutter

2Großeltern

3Urgroßeltern

5Ururgroßeltern

Prof. Dr. Margarita Esponda

Funktionale Programmierung

25

Fibonacci-Zahlen

11

2

35

813

21

Prof. Dr. Margarita Esponda

Funktionale Programmierung

26

Fibonacci-Zahlen

Blumen

1 2

3 5

8 13

21 34

Prof. Dr. Margarita Esponda

27

Fibonacci-Zahlen

0 1

fib(0) fib(1)

1

fib(2)

+

Prof. Dr. Margarita Esponda

Funktionale Programmierung

28

Fibonacci-Zahlen

0 1

fib(0) fib(1)

1

fib(2) fib(3)

+ 2

Prof. Dr. Margarita Esponda

Funktionale Programmierung

29

Fibonacci-Zahlen

0 1

fib(0) fib(1)

1

fib(2) fib(3)

+ 2 3

fib(4)

Prof. Dr. Margarita Esponda

Funktionale Programmierung

30

Fibonacci-Zahlen

0 1

fib(0) fib(1)

1

fib(2) fib(3)

2 3

fib(4) fib(5)

+ 5

Prof. Dr. Margarita Esponda

Funktionale Programmierung

31

Fibonacci-Zahlen

0 1

fib(0) fib(1)

1

fib(2)

+2

fib(3)

3

fib(4)

5

fib(5)

8

fib(6)

13

fib(7)

. . . . .

fib(n)fib(n-2) fib(n-1). . . . . +

fib ( 0 ) = 0

fib ( 1 ) = 1

fib ( n ) = fib ( n-2 ) + fib ( n-1 ) für alle n>1

Formale rekursive Definition:

+

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Berechnung der Fibonacci-Zahlen1. Lösung

fib 5

fib 3 fib 4

fib 1 fib 2 fib 2 fib 3

fib 0 fib 1

fib 7

fib 6

fib 4 fib 5

fib 2 fib 3 fib 3 fib 4

fib 0 fib 1 fib 1 fib 2 fib 0 fib 1 fib 1 fib 2 fib 1 fib 2 fib 2 fib 3

fib 0 fib 1 fib 0 fib 1 fib 1 fib 2fib 0 fib 1

fib 0 fib 1wiederholte Berechnungen der fib-Funktion

Beispiel: fib 7

fib 0 = 0fib 1 = 1fib n = fib (n-1) + fib (n-2)

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Berechnung der Fibonacci-Zahlen

fib 5

fib 3 fib 4

fib 1 fib 2 fib 2 fib 3

fib 0 fib 1

fib 7

fib 6

fib 4 fib 5

fib 2 fib 3 fib 3 fib 4

fib 0 fib 1 fib 1 fib 2 fib 0 fib 1 fib 1 fib 2 fib 1 fib 2 fib 2 fib 3

fib 0 fib 1 fib 0 fib 1 fib 1 fib 2fib 0 fib 1

fib 0 fib 1

Beispiel: fib 7

Fallgrube

Wenn wir fib 40 mit unserer rekursiven Implementierung berechnen,

wird:

fib 39 einmal berechnetfib 38 2 mal berechnetfib 37 3 mal berechnetfib 36 5 mal berechnetfib 35 8 mal berechnet. . .fib 0 165 580 141 mal berechnet

Beim Aufruf von fib 40 werden 331 160 281 Funktionsaufrufe gemacht

Berechnung der Fibonacci-ZahlenWie viele Reduktionsschritte brauchen wir, um fib n zu berechnen?

fib 0

1

fib 1

1

fib 2 fib 3 fib 4 fib 5

8

fib 6

13

Die Anzahl der Reduktionen für fib n ist gleich fib (n+1)

Die Anzahl der rekursive Aufrufe ist eine

exponentielle Funktion von n.

+ =2 3+ =1

5+ =2 3

8+ =3 5

13+ =3 5

532 Reduktionen

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Berechnung der Fibonacci-Zahlen

2. Lösung

fib' n = quickFib 0 1 n

where

quickFib a b 0 = a

quickFib a b n = quickFib b (a+b) (n-1)

quickFib funktioniert nur, wenn diese mit den ersten zwei Fibonacci-Zahlen gestartet wird.

Zähler

Innerhalb jedes rekursiven Aufrufs wird eine neue Fibonacci-Zahl berechnet und der Zähler verkleinert. Die neue Zahl und ihr Vorgänger werden beim nächsten rekursiven Aufruf als Parameter weitergegeben.

Für die Berechnung von quickFib n benötigen wir n Reduktionen,

Anzahl der Reduktionen

Prof. Dr. Margarita Esponda

Funktionale Programmierung

36

Fibonacci-Zahlen

nextFib :: (Integer, Integer) -> (Integer, Integer)nextFib (a,b) = (b, a+b)

fib n = fst ( fibTuple n )

fibTuple n | n==0 = (0, 1) | otherwise = nextFib (fibTuple (n-1))

Text

3. Lösung mit Tupeln:

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Listen

Symbol Name Bedeutung

[ ] nil leere Liste

(:) cons am Anfang anfügen

Listen sind die wichtigsten Datenstrukturen in funktionalen

Programmiersprachen

Listen stellen Sammlungen von Objekten dar, die den gleichen

Datentyp besitzen

Listen sind dynamische Datenstrukturen, die mit Hilfe folgender

Daten-Konstruktoren erzeugt werden können

Prof. Dr. Margarita Esponda

Funktionale Programmierung

ListenListen sind rekursive Strukturen:

Eine Liste ist entweder leer

[]

oder ein konstruierter Wert, der aus einem Listenkopf x und einer Restliste xs besteht.

x : xs

Der Typ einer Liste, die Elemente des Typs t enthält, wird

mit [t] bezeichnet.

head tail

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Ausdrücke mit ListenBeispiele:

[1, 2, 3] :: [Integer]

1: [0,3,7] :: [Integer]

[ [0.3, 0.0], [] ] :: [[Double]]

'a' : "Hello" :: [Char]

[( 3, 0 ), ( 2, 1)] :: [ (Integer, Integer) ]

[ True, True, False ] :: [ Bool ]

[ e1, e2, e3, … ,en ]

Syntaktische Abkürzung:

Datentyp

Allgemeine Syntax:

Ausdruck

e1:[e2:[e3: … :en:[]]] e1:e2: … :en:[]

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Ausdrücke mit ListenBeispiele:

"hello"

[1, 2, 3] 1:[2, 3] 1 : 2 : 3 : []

[( 3, 0 ), ( 2, 1)]

'h' : "ello"

['h', 'e', 'l', 'l', 'o']

( 3, 0 ) : [( 2, 1)]

[[3, 0 ], [2, 1]] [3, 0] : [2, 1] : []

equiv.

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Funktionen mit Listen

kopf :: [ Integer ] -> Integer

kopf (x:xs) = x

kopf [] = error "ERROR: empty list"

rumpf :: [ Integer ] -> [ Integer ]

rumpf (x:xs) = xs

rumpf [] = error "ERROR: empty list"

Prof. Dr. Margarita Esponda

Funktionale Programmierung

summe :: [Integer] -> Integer

summe ls = if ls == []

then 0

else ( kopf ls ) + summe (rumpf ls)

Addiert alle Zahlen innerhalb einer Liste

Lösung mit Pattern-Matching über der Listenstruktur

summe :: [Integer] -> Integer

summe [] = 0

summe (x : xs) = x + summe xs

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Funktionen mit Listen

Funktionsdefinitionen mit Listen

multList :: [Integer] -> Integer

multList [] = error "the function is not defined for []"

multList [x] = x

multList (x:xs) = x * multList xs

laenge :: [Int] -> Int

laenge [] = 0

laenge (x:xs) = 1 + laenge xs

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Zehnersystem → Binärsystem

42 0

121

42 10

10

5

0

2

1

011

0

= 1010102mod 2div 2

dec2bin :: Int -> [Int]

dec2bin n | n<2 = [n]

| otherwise = dec2bin (n`div`2) ++ [n `mod`2]

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Funktionen mit Listen

drehe [1,2,3] ⇒ drehe [2,3] ++ [1]

⇒ drehe [3] ++ [2] ++ [1]

⇒ drehe [] ++ [3] ++ [2] ++ [1]

⇒ [] ++ [3] ++ [2] ++ [1]

drehe [] = []

drehe (x:xs) = drehe xs ++ [x]

Verkettungsoperator

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Funktionen mit Listen

binary2decimal xs = bin2dec ( drehe xs)

bin2dec :: [Int] -> Int

bin2dec [] = 0

bin2dec (x:xs) = x + 2*(bin2dec xs)

1011012 =

= 2(2(2(2(2(1)+0)+1)+1)+0)+1

1*25 + 0*24 + 1*23 + 1*22 + 0*21 + 1*20

Prof. Dr. Margarita Esponda

Funktionale Programmierung

Funktionen mit Listen

bitXOr :: [Int] -> [Int] -> [Int]

bitXOr [] [] = []

bitXOr (x:xs) (y:ys) = (exoder x y): (bitXOr xs ys)

bitXOr _ _ = error "the two lists are not of the same length"

exoder :: Int -> Int -> Int

exoder x y | x==y = 0

| otherwise = 1

Prof. Dr. Margarita Esponda

Funktionale Programmierung