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

Map, filter und List Comprehension

weiter

weiter

map

Literatur
LYAH: Maps and filters
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
LYAH: I'm a list comprehension
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