home Funktionale Programmierung: Fold-Funktionen Prof. Dr. Uwe Schmidt FH Wedel

Fold-Funktionen

weiter

weiter

Literatur
weiter
Typische Struktur
für einfache Listenfunktionen
 
f          :: [a] -> b
 
f  []      =  e
f (x : xs) =  x `op` f xs
weiter
Beispiele
sum          :: Num a => [a] -> a
 
sum  []      =  0
sum (x : xs) =  x + sum xs
 
length          :: [a] -> Int
 
length  []      =  0
length (x : xs) =  1 + length xs
 
concat            :: [[a]] -> [a]
 
concat  []        =  []
concat (xs : xss) =  xs ++ concat xss
 
and          :: [Bool] -> Bool
 
and  []      =  True
and (x : xs) =  x && and xs
 
fast
 
reverse          :: [a] -> [a]
 
reverse  []      =  []
reverse (x : xs) =  reverse xs ++ [x]
?
Transformation in obiges Schema?
weiter
Verarbeitung
x1 : (x2 : (x3 : []))
 
wird transformiert in
 
x1 `op` (x2 `op` (x3 `op` e))
weiter
Abstraktion
von der Operation
 
Trennung von Kontrollstruktur und Verarbeitung
weiter
Definition: foldr
fold right
 
`op` bezeichnet eine rechtsassoziative Operation
 
foldr               :: (a -> b -> b) -> b ->
                       [a] -> b
 
foldr op e  []      =  e
foldr op e (x : xs) =  x `op` (foldr op e xs)
weiter
?
Rekursionstyp?
weiter
Beispiele
sum    = foldr (+) 0
 
concat = foldr (++) []
 
and    = foldr (&&) True
 
length = foldr oneplus 0
         where
         oneplus x n = 1 + n
 
-- kürzer
 
length = foldr (\ x -> (1+)) 0
 
-- noch kürzer
 
length = foldr (const (1+)) 0
weiter
?
length mit sum?
weiter
?
reverse mit foldr?
weiter
?
Laufzeit von reverse mit foldr?
weiter
?
Identität für Listen mit foldr?
weiter
?
map mit foldr?
weiter
filter mit map implementiert.
map mit foldr implementiert.
merke
Aber: Direkte Implementierung von map kann effizienter sein als foldr.
?
linksassoziative Operationen mit fold?
weiter
Beispiel
Horner-Schema
 
    decimal [x0, x1, x2]
  =
    ((* 10 + x0) * 10 + x1) * 10 + x2
  =
    ((`op` x0) `op` x1) `op` x2
    where
    n `op` x = n * 10 + x
weiter
foldl
fold left
 
    foldl op e [x0, x1, ..., xn]
  =
    (...((e `op` x0) `op` x1) ...) `op` xn
weiter
Definition
foldl               :: (b -> a -> b) -> b ->
                       [a] -> b
 
foldl op e  []      =  e
foldl op e (x : xs) =  foldl op (e `op` x) xs
weiter
?
Rekursionstyp?
weiter
Beispiel
reverse = foldl snoc []
          where
          snoc xs x = x : xs
 
-- oder
 
reverse = foldl (flip (:)) []
weiter
?
Laufzeit von reverse mit foldl?
weiter
?
concat mit foldl?
weiter
?
Laufzeit von concat mit foldl?
weiter
?
Maximum und Minimum über Listen mit fold?
weiter
Problem
Wert der leeren Liste?
weiter
Lösung
Varianten von fold für nicht leere Listen
 
foldr1  :: (a -> a -> a) -> [a] -> a
 
foldr1 op (x : xs)
  | null xs     = x
  | otherwise   = x `op` foldr1 op xs
 
foldl1  :: (a -> a -> a) -> [a] -> a
 
foldl1 op (x : xs)
  = foldl op x xs
weiter
merke
Das letzte (foldr) oder das erste Element (foldl) wird für das fehlende e verwendet.
weiter
Beispiele
minimum :: Ord a => [a] -> a
minimum = foldl1 min
 
maximum :: Ord a => [a] -> a
maximum = foldl1 max
weiter
scanl
Verarbeiten aller Anfangsstücke einer Liste
 
    scanl op e [x0, x1, x2, ...]
  =
    [ e
    , e `op` x0
    , (e `op` x0) `op` x1
    , ((e `op` x0) `op` x1) `op` x2
    , ...
    ]
weiter
Beispiel
die zu einer Zahlenfolge gehörige Reihe
 
scanl (+) 0
 
-- Beispiele
 
scanl (+) 0 (repeat 1)         = ???
scanl (+) 0 [1..]              = ???
weiter
Definition
scanl               :: (a -> b -> b) -> b ->
                       [a] -> [b]
 
scanl op e  []      = []
scanl op e (x : xs) = e : scanl op (e `op` x) xs
weiter
?
scanl mit fold?
Gesetze
für fold Funktionen
1. Dualitätsgesetz
für assoziative Operationen `op` mit e als neutralem Element und endlichen Listen xs gilt
 
foldr op e xs = foldl op e xs
weiter
Beispiele
sum     = foldl (+) 0
and     = foldl (&&) True
or      = foldl (||) False
concat  = foldl (++) []
weiter
2. Dualitätsgesetz
Wenn op1, op2 die folgenden Bedingungen erfüllen, dann gilt für endliche Listen xs:
 
x `op1` (y `op2` z) = (x `op1` y) `op2` z
x `op1` e           = e `op2` x
 
foldr op1 e xs = foldl op2 e xs
weiter
merke
Das erste Gesetz ist Spezialfall des zweiten.
weiter
?
Beweis?
weiter
?
foldl und foldr auf unendlichen Listen?

Letzte Änderung: 18.09.2019
© Prof. Dr. Uwe Schmidt
Prof. Dr. Uwe Schmidt FH Wedel