home Funktionale Programmierung: Map, filter und List Comprehension Prof. Dr. Uwe Schmidt FH Wedel

Map, filter und List Comprehension

weiter

weiter

map

Literatur
weiter
Verarbeitung
aller Elemente einer Liste
weiter
Anwenden
einer Funktion auf jedes Element einer Liste
 
map square [1, 2, 3] = [1, 4, 9]
 
map (<2)   [1, 2, 3] = [True, False, False]
weiter
Definition
map            :: (a -> b) -> [a] -> [b]
 
map f []       =  []
map f (x : xs) =  f x : map f xs
weiter
Beispiel
sum
sum          :: Num a => [a] -> a
sum []       =  0
sum (x : xs) =  x + sum xs
upto
upto          :: Integral a => a -> a -> [a]
upto m n
  | m > n     = []
  | otherwise = m : upto (m + 1) n
 
from          :: Integral a => a -> [a]
from n        = n : from (n + 1)
?
sum (map square (upto 1 100)) = ???
weiter
Syntax
für bessere Lesbarkeit
 
[m .. n]  = upto m n
[m .. ]   = from m
weiter
Gesetze
map id      = id
map (f . g) = map f . map g
weiter
?
Wo sind diese Gesetze anwendbar?
weiter
merke
Datenstrukturen, die eine map-Funktion besitzen, die diese beiden Gesetzte erfüllt, heißen Funktor.
weiter
?
Funktor für Maybe?
weiter
weitere Gesetze
f . head         =  head . map f
map f . tail     =  tail . map f
map f . reverse  =  reverse . map f
map f . concat   =  concat . map (map f)
 
map f (xs ++ ys) = map f xs ++ map f ys
weiter

weiter

filter

Selektion
von Elementen einer Liste
weiter
Anwenden
eines Prädikates auf alle Elemente einer Liste
 
filter even [1, 2, 3, 4] = [2, 4]
 
(sum . filter even) [1..10] = 30
 
(sum . map square . filter even) [1..10] = 220
weiter
Definition
filter            :: (a -> Bool) -> [a] -> [a]
 
filter p []       =  []
filter p (x : xs)
  | p x           = x : filter xs
  | otherwise     =     filter xs
weiter
Eigenschaften
filter p . filter q = filter (p `and` q)
 
and       :: (a -> Bool) ->
             (a -> Bool) -> (a -> Bool)
and p q x = p x && q x
 
filter p . concat = concat . map (filter p)
weiter
filter
definiert durch map und concat
 
filter p = concat . map box
           where
           box x = if p x then [x] else []
weiter

weiter

list comprehension

Literatur
weiter
2. Notation
zum Arbeiten mit map und filter
weiter
Beispiel .1
  [ x * x | x <- [1..5]]
=
  map square [1..5]
weiter
Beispiel .2
  [ x * x | x <- [1..5], odd x]
=
  (map square . filter odd) [1..5]
weiter
Definition
Transformationsregeln
weiter
Generator Regel
[ e | x <- xs, Q ] = concat (map f xs)
                     where
                     f x = [e | Q]
weiter
Wächter Regel
[ e | p, Q ]       = if p
                     then [e | Q]
                     else []
weiter
?
Beweis: Beispiel .2 ?
Beispiele
ge = [ (i, j) | i <- [1..5]
              , j <- [1..5]
              , i <= j
     ]
weiter
?
Ergebnis?
Gesetze
über list comprehension
 
[ f x | x <- xs ]     = map f xs
[ x   | x <- xs, p x] = filter p xs
weiter
?
Was ist besser: list comprehension oder map und filter?
weiter

weiter

Beispiel: List Comprehension

   1module Pythagoras where
   2
   3type Triangle   = (Int, Int, Int)
   4
   5triples         :: Int -> [Triangle]
   6triples n
   7    = [ (x, y, z) | x <- [1..n]
   8                  , y <- [x..n]
   9                  , z <- [y..n]
  10                  , x + y > z
  11      ]
  12
  13triads          :: Int -> [Triangle]
  14triads n
  15    = [ tri | tri <- triples n
  16      , pyth tri
  17      ]
  18    where
  19    pyth (x, y, z) = x*x + y*y == z*z
  20
  21triads'         :: Int -> [Triangle]
  22triads' n
  23    = [ tri | tri <- triads n
  24      , minimal tri
  25      ]
  26    where
  27    minimal (x, y, z) = x `gcd` y `gcd` z == 1
weiter

weiter

zip und zipWith

map
erzeugt aus einstelligen Funktionen auf Element-Typen einstellige Funktionen auf Listen.
 
map :: (a -> b) -> ([a] -> [b])
weiter
?
Auch sinnvoll für 2-stellige und n-stellige Funktionen?
weiter
zip
verarbeitet 2 Listen zu einer neuen Resultat-Liste
 
zip :: [a] -> [b] -> [(a,b)]
 
zip  []     ys    = []
zip  xs     []    = []
zip (x:xs) (y:ys) = (x, y) : zip xs ys
weiter
Beispiel
Suchen aller Positionen, an denen ein bestimmter Wert steht:
 
positions       :: Eq a => a -> [a] -> [Int]
 
positions x xs  = [ i | (i, y) <- zip [0..] xs, x == y ]
weiter
?
Punktfreie Version von positions?
weiter
Beispiel
Suche der 1. Position, an der ein bestimmter Wert steht (oder -1):
 
position        :: Eq a => a -> [a] -> Int
 
position x xs   = head (positions x xs ++ [-1])
weiter
?
Punktfreie Version von position?
weiter
zipWith
"anheben" (liften) von 2-stelligen Funktionen auf Listen
 
zipWith                :: (a -> b -> c) -> ([a] -> [b] -> [c])
zipWith f xs ys        =  map (uncurry f) (zip xs ys)
weiter
?
Beispiele für sinnvolle Anwendungen?
Vektorrechnung?
weiter
zipWith
besser: Direkte Variante
 
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
 
zipWith f  []     ys          = []
zipWith f  xs     []          = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
weiter
?
zip mit zipWith implementieren?
weiter
unzip
inverse Operation zu zip
 
unzip  :: [(a,b)] -> ([a], [b])
 
unzip  =  pair (map fst, map snd)
 
uncurry zip . unzip = id
weiter
?
Herleitung der Definition von unzip?

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