Programmierkurs II

Werbung
Programmierkurs II
Higher Order Functions
• ÜbergabeparameterkönnenFunktionensein.
• RückgabewertekönnenFunktionensein.
HigherOrderFunctions
• InHaskell nimmtjedeFunktiongenaueinenParameter
entgegen.
• WiekönnennunFunktionenmehrereParameterannehmen?
– CURRYING!
*Main> :t max
max :: Ord a => a -> a -> a
*Main> :t max 3
max 3 :: (Num a, Ord a) => a -> a
Currying
*Main> max 3 5
5
*Main> (max 3) 5
5
• InHaskell nimmtjedeFunktiongenaueinenParameter
entgegen.
• WiekönnennunFunktionenmehrereParameterannehmen?
– CURRYING!
*Main> :t max
max :: Ord a => a -> (a -> a)
*Main> :t max 3
max 3 :: (Num a, Ord a) => a -> a
Currying
*Main> max 3 5
5
*Main> (max 3) 5
5
• WennwireineFunktionmitzuwenigenParameteraufrufen,
bekommenwireineFunktionzurück,dienichtvollständig
ausgeführtwurde.
• DadurchkönnenwirFunktionenbauen,welchewiranandere
Funktionenweiterreichen,odereinfach–onthe fly- mitDaten
füttern.
multThree :: (Num a) => a -> a -> a -> a
multThree x y z = x * y * z
Vorteil
Code
SchreibenwireineFunktion,dieeinenübergebenenWertmit
derZahl100vergleicht:
compareWithHundred :: (Num a, Ord a) => a -> Ordering
compareWithHundred x = compare 100 x
Warumbenötigenwirüberhauptdas‘x‘?
compareWithHundred' :: (Num a, Ord a) => a -> Ordering
compareWithHundred' = compare 100
Code
Vorteil
SchreibenwireineFunktion,dieeinenübergebenenWertmit
derZahl10addiert:
add10 :: (Num a) => a -> a
add10 = (+10)
CheckenwirdieTypsignatur:
*Main> :t (+10)
(+10) :: Num a => a -> a
Beispiel- Operatoren
Waspassiert,wennwireinepartielleFunktionanzeigenwollen?
*Main> multThree 3 4
<interactive>:30:1:
No instance for (Show (a0 -> a0))
(maybe you haven't applied enough arguments to a function?)
arising from a use of ‘print’
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
Beispiel– Funktionenanzeigen
SchreibenwireineFunktion,welcheeineübergebeneFunktion
zweimalaufihrArgumentanwendet:
applyTwice ::
applyTwice
FunktionalsÜbgergabeparameter
SchreibenwireineFunktion,welcheeineübergebeneFunktion
zweimalaufihrArgumentanwendet:
applyTwice :: (a -> a) -> a -> a
applyTwice
FunktionalsÜbgergabeparameter
SchreibenwireineFunktion,welcheeineübergebeneFunktion
zweimalaufihrArgumentanwendet:
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
Beispiel:
FunktionalsÜbgergabeparameter
SchreibenwireineFunktion,welcheeineübergebeneFunktion
zweimalaufihrArgumentanwendet:
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
Beispiel:
*Main> applyTwice (+3) 10
16
*Main> applyTwice ("Ha" ++) "llo"
"HaHallo"
FunktionalsÜbgergabeparameter
zip'
zip'
zip'
zip'
:: [a]
_ [] =
[] _ =
(x:xs)
-> [b] -> [(a,b)]
[]
[]
(y:ys) = (x,y):zip' xs ys
WirddurcheinezusätzlicheFunktionerweitert:
zipWith'
zipWith'
zipWith'
zipWith'
:: (a ->
_ [] _ =
_ _ [] =
f (x:xs)
b -> c) -> [a] -> [b] -> [c]
[]
[]
(y:ys) =
Erweiterungvonzip
zip'
zip'
zip'
zip'
:: [a]
_ [] =
[] _ =
(x:xs)
-> [b] -> [(a,b)]
[]
[]
(y:ys) = (x,y):zip' xs ys
WirddurcheinezusätzlicheFunktionerweitert:
zipWith'
zipWith'
zipWith'
zipWith'
:: (a ->
_ [] _ =
_ _ [] =
f (x:xs)
b -> c) -> [a] -> [b] -> [c]
[]
[]
(y:ys) = f x y : zipWith' f xs ys
Erweiterungvonzip
Code
BeieinerFaltungwerdendieElementeeinerListemitHilfeeines
Operatorszusammengefasst.
Beispiele:
• Summe
• Produkt
• Listenkonkatenation
Faltungen
WasfälltbeidiesenbeidenFunktionenauf?
sum' :: (Num a) => [a] -> a
sum' []
= 0
sum' (x:xs) = x + sum' xs
product' :: (Num a) => [a] -> a
product' []
= 1
product' (x:xs) = x * sum' xs
Faltungen
DefinitionmitStartwertundeinerzweistelligenFunktionf auf
einerListex:
f x1 (f x2 ...(f xn s))
DieFunktionfoldR benötigtalsoeineFunktionf,einenStartwerts und
eineListe.
foldR :: (_ -> _ -> _) -> _ -> [_] -> _
foldR _ s []
= s
foldR f s (x:xs) = f x (foldR f s xs)
FaltungvonrechtsmitStartwert
DefinitionmitStartwertundeinerzweistelligenFunktionf auf
einerListex:
f x1 (f x2 ...(f xn s))
DieFunktionfoldR benötigtalsoeineFunktionf,einenStartwerts und
eineListe.
foldR :: (b -> a -> a) -> a -> [b] -> a
foldR _ s []
= s
foldR f s (x:xs) = f x (foldR f s xs)
FaltungvonrechtsmitStartwert
DieFunktionsdefinitionlässtsichanalogzurSummedefinieren,nurdass
wirdiezusätzlichenParameteranstellevon0und+verwenden.
foldR :: (b -> a -> a) -> a -> [b] -> a
foldR _ s []
= s
foldR f s (x:xs) = f x (foldR f s xs)
sum' :: (Num a) => [a] -> a
sum' []
= 0
sum' (x:xs) = x + sum' xs
FaltungvonrechtsmitStartwert- Vergleich
Beispiel:
Liste
[1,2,3]
[1,2]
[1]
[]
Startwert
0
+
3
+
5
+
6
FaltungvonrechtsmitStartwert
Code:
sum'' :: [Int] -> Int
sum'' xs = foldr (+) 0 xs
SummenfunktiondurchFaltung
Code:
sum'' :: [Int] -> Int
sum'' xs = foldr (+) 0 xs
Beispiel:
sum [1, 2, 3]
foldr (+) 0 [1, 2, 3]
foldr (+) 0 (1:(2:(3:[])))
(1+(2+(3+0)))
SummenfunktiondurchFaltung
Code:
product'' :: [Int] -> Int
product'' xs = foldr (*) 1 xs
Beispiel:
product [1, 2, 3]
foldr (*) 1 [1, 2, 3]
foldr (*) 1 (1:(2:(3:[])))
(1*(2*(3*1)))
ProduktdurchFaltung
Vereinfachen?
sum'' :: [Int] -> Int
sum'' xs = foldr (+) 0 xs
product'' :: [Int] -> Int
product'' xs = foldr (*) 1 xs
Vereinfachen
xs kannausderGleichunggestrichenwerden:
sum'' :: [Int] -> Int
sum'' = foldr (+) 0
product'' :: [Int] -> Int
product'' = foldr (*) 1
Vereinfachen
Code:
length' :: [a] -> Int
length' []
= 0
length' (_:xs) = 1 + length' xs
Auswertung:
length‘ [1, 2, 3]
=
length‘ (1:(2:(3:[])))
=
1+(1+(1+0)) = 3
length durchFaltung- Vorlesung
Code:
length' :: [a] -> Int
length' []
= 0
length' (_:xs) = 1 + length' xs
Auswertung:
\_ n -> 1 + n
length‘ [1, 2, 3]
=
length‘ (1:(2:(3:[])))
=
1+(1+(1+0)) = 3
length durchFaltung - Vorlesung
Code:
length' :: [a] -> Int
length' []
= 0
length' (_:xs) = 1 + length' xs
Auswertung:
length‘ [1, 2, 3]
=
length‘ (1:(2:(3:[])))
=
1+(1+(1+0)) = 3
\_ n -> 1 + n
Einsetzen:
length'' :: [a] -> Int
length'' = foldr (\_ n -> 1 + n) 0
length durchFaltung - Vorlesung
Code:
reverse' :: [a] -> [a]
reverse' []
= []
reverse' (x:xs) = reverse‘ xs ++ [x]
Auswertung:
reverse‘ [1, 2, 3]
=
reverse‘ (1:(2:(3:[])))
=
(([] ++ [3]) ++ [2]) ++ [1]
reverse durchFaltung- Vorlesung
Code:
reverse' :: [a] -> [a]
reverse' []
= []
reverse' (x:xs) = reverse‘ xs ++ [x]
Auswertung:
\x xs -> xs ++ [x]
reverse‘ [1, 2, 3]
=
reverse‘ (1:(2:(3:[])))
=
(([] ++ [3]) ++ [2]) ++ [1]
reverse durchFaltung- Vorlesung
Code:
reverse' :: [a] -> [a]
reverse' []
= []
reverse' (x:xs) = reverse‘ xs ++ [x]
Auswertung:
reverse‘ [1, 2, 3]
=
reverse‘ (1:(2:(3:[])))
=
(([] ++ [3]) ++ [2]) ++ [1]
\x xs -> xs ++ [x]
Einsetzen:
reverse'' :: [a] -> [a]
reverse'' = foldr (\x xs -> xs ++ [x]) []
reverse durchFaltung- Vorlesung
Code:
map' :: (a -> b) -> [a] -> [b]
map' f []
= []
map' f(x:xs) = f x : map‘ f xs
Auswertung:
map‘ f [1, 2, 3]
=
map‘ f (1:(2:(3:[])))
=
f 1:(f 2: (f 3: []))
map durchFaltung
Code:
map' :: (a -> b) -> [a] -> [b]
map' f []
= []
map' f(x:xs) = f x : map‘ f xs
Auswertung:
\x xs -> f x : xs
map‘ f [1, 2, 3]
=
map‘ f (1:(2:(3:[])))
=
f 1:(f 2: (f 3: []))
map durchFaltung
Code:
map' :: (a -> b) -> [a] -> [b]
map' f []
= []
map' f(x:xs) = f x : map‘ f xs
Auswertung:
\x xs -> f x : xs
map‘ f [1, 2, 3]
=
map‘ f (1:(2:(3:[])))
=
f 1:(f 2: (f 3: []))
Einsetzen:
map' :: (a -> b) -> [a] -> [b]
map' f = foldr (\x xs -> f x : xs) []
map durchFaltung
Wiekannmandiemap-FunktionmitHilfevonfoldr darstellen?
map' :: (a -> b) -> [a] -> [b]
map' f = foldR ((:).f) []
map durchFaltung- Alternative
Waskommtraus?
*Main> foldr ($) 7 [(/2), (*10), sqrt, (+2)]
*Main> scanr ($) 7 [(/2), (*10), sqrt, (+2)]
Faltung- Beispiel
Waskommtraus?
*Main> foldr ($) 7 [(/2), (*10), sqrt, (+2)]
15.0
*Main> scanr ($) 7 [(/2), (*10), sqrt, (+2)]
[15.0,30.0,3.0,9.0,7.0]
Code
Faltung- Beispiel
MitStartwert:
foldR :: (b -> a -> a) -> a -> [b] -> a
foldR _ s []
= s
foldR f s (x:xs) = f x (foldR f s xs)
OhneStartwert:
foldR' :: (a -> a -> a) -> [a] -> a
foldR' f (x:xs) = f x (foldR' f xs)
Einfachmaltesten:
*Main> foldR' (+) [1..10]
FaltungvonrechtsOHNEStartwert
WirbenötigenabermindestenseinElementinderListe!
foldR' :: (a -> a -> a) -> [a] -> a
foldR' _ [x]
= x
foldR' f (x:xs) = f x (foldR' f xs)
VordefinierteFunktioninderPrelude:foldr1
FaltungvonrechtsOHNEStartwert
DefinitionmitStartwertundeinerzweistelligenFunktionf auf
einerListex:
f (f (f s x1) x2) xn
AndersalsbeiderFaltungvonrechtswirddieListealsonicht
zuerstganzbiszumEndedurchlaufen,bevormitderAuswertung
derFunktionf begonnenwird.
FaltungvonlinksmitStartwert
Beispiel:
Startwert
1
*
1
*
2
*
3
Liste
[1,2,3]
[2,3]
[3]
[]
FaltungvonlinksmitStartwert
foldL :: (a -> b -> a) -> a -> [b] -> a
foldL _ s []
= s
foldL f s (x:xs) = foldL f (f s x) xs
VergleichzufoldR
foldR :: (b -> a -> a) -> a -> [b] -> a
foldR _ s []
= s
foldR f s (x:xs) = f x (foldR f s xs)
FaltungvonlinksmitStartwert
VorsichtinderGleichungwirddieFunktionfoldL aufgerufen!
foldL' :: (a -> a -> a) -> [a] -> a
foldL' f (x:xs) = foldL f x xs
VordefinierteFunktioninderPrelude:foldl1
FaltungvonlinksOHNEStartwert
WasistdasErgebnis?
*Main> foldl (-) 1 [1..3]
*Main> foldr (-) 1 [1..3]
UnterschiedzwischenLinks- undRechtsfaltung
WasistdasErgebnis?
*Main> foldl (-) 1 [1..3]
-5
*Main> foldr (-) 1 [1..3]
1
foldl (-) 1 [1..3] =
=
=
=
-(-(-11)2)3
-(- 0 2)3
-(-2)3
-5
foldr (-) 1 [1..3] =
=
=
=
-1(-2(-31))
-1(-22)
-10
1
UnterschiedzwischenLinks- undRechtsfaltung
Code
Aufgabe:
WennwirüberalleElementeeinerunendlichenListedieWurzel
ziehenunddieeinzelnenErgebnisseaufsummieren,wieviele
ElementeausderListewerdenmaximalgezogenbisdieZahl
1000überschrittenwird.
Einbisschenüberlegen...
Aufgabe:
WennwirüberalleElementeeinerunendlichenListedieWurzel
ziehenunddieeinzelnenErgebnisseaufsummieren,wieviele
ElementeausderListewerdenmaximalgezogenbisdieZahl
1000überschrittenwird.
*Main> length (takeWhile (<1000) (scanl1 (+) (map sqrt [1..])))
Einbisschenüberlegen...
Aufgabe:
WennwirüberalleElementeeinerunendlichenListedieWurzel
ziehenunddieeinzelnenErgebnisseaufsummieren,wieviele
ElementeausderListewerdenmaximalgezogenbisdieZahl
1000überschrittenwird.
*Main> length (takeWhile (<1000) (scanl1 (+) (map sqrt [1..])))
*Main> length . takeWhile (<1000) . scanl1 (+) . map sqrt $ [1..]
Einbisschenüberlegen...
Herunterladen