Haskell: Higher Order Programming Linguaggi Funzionali /aa. 03 - M.Bellia Haskell: Higher Order Programming Higher Order Programming: headR, tailR, rote90 Funzioni come valori di parametri Esempi di programmi: rote90 Funzioni: map, fold, filter Verifica: reverse.reverse = id Esercizi 12/7/2018
Higher Order Programming: headR, tailR, rote90 Linguaggi Funzionali /aa. 03 - M.Bellia Higher Order Programming: headR, tailR, rote90 rote90b p | (length (head p)) == 0 = [] | otherwise = (reverse(headR p)):(rote90b(tailR p)) where headR [] = [] headR (x:xs) = (head x):(headR xs) tailR [] = [] tailR (x:xs) = (tail x):(tailR xs) Stessa struttura di controllo (f x) : (g xs) per differenti f e g 12/7/2018
Funzioni come valori di parametri (f x) : (g xs) astratto e astrazione funzionale: \ f -> \g -> (f x):(g xs) headR [] = [] headR (x:xs) = (head x):(headR xs) tailR [] = [] tailR (x:xs) = (tail x):(tailR xs) fR [] _ = [] fR (x:xs) f= (f x):(fR xs f) 12/7/2018
Esempi di programmi rote90b p | (length (head p)) == 0 = [] | otherwise = (reverse(headR p)):(rote90b(tailR p)) where headR [] = [] headR (x:xs) = (head x):(headR xs) tailR [] = [] tailR (x:xs) = (tail x):(tailR xs) rote90b p | (length (head p)) == 0 = [] | otherwise = (reverse(fR p head)):(rote90b(fR p tail)) where fR [] _ = [] fR (x:xs) f = (f x):(fR xs f) 12/7/2018
Funzioni: map, fold, filter Linguaggi Funzionali /aa. 03 - M.Bellia Funzioni: map, fold, filter Sono funzionali Applicano funzioni a liste: map:: (a -> b) -> [a] -> [b] map f [x1,…,xn] = [(f x1),…,(f xn)] foldr:: (a -> b -> b) -> b -> [a] -> b foldr f k [x1,…,xn] = f x1 (f x2 (…(f xn k)…)) foldl:: (b -> a -> b) -> b -> [a] -> b foldl f k [x1,…,xn] = f(f(…(f k x1)…)xn-1)xn filter:: (a -> bool) -> [a] -> [a] filter p [x1,…,xn] = [xk1,…,xkh] 1≤i≤n, ((p xi) 1≤j≤k, xi=xkj 1 ≤ k1<…< kh ≤ n 12/7/2018
map, fold, filter: implementazione map:: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = (f x):(map f xs) foldr:: (a -> b -> b) -> b -> [a] -> b foldr f n [] = n foldr f n (x:xs) = f x (foldr f n xs) foldl:: (b -> a -> b) -> b -> [a] -> b foldl f n [] = n foldl f n (x:xs) = foldl f (f n x) xs filter:: (a -> bool) -> [a] -> [a] filter p [] = [] filter p (x:xs) | (p x) = x:(filter p xs) | otherwise = filter p xs 12/7/2018
map, fold, filter: semplici calcoli Associatività -- calcolare: foldr (+) 0 [2,3,4,5] foldl (+) 0 [2,3,4,5] foldr (-) 0 [2,3,4,5] = 2 - (3 - (4 - (5 - 0))) foldl (-) 0 [2,3,4,5] = ((((0 -2) - 3) - 4) - 5) calcolare: map ((:[]).(2*)) [3,7,2] foldr (max) 0 [-2,9,7,-3,12] 12/7/2018
map, fold, filter: applicazioni Ex 9.1 (craft2) doubleAll -- 3 definizioni: (1) ric. primitiva, (2) list-comprehension, (3) map (1) doubleAll xs = if (null xs) then [] else (2*(head xs)):doubleAll(tail xs) (2) doubleAll xs = [2 * x | x <- xs] (3) doubleAll = map (2 `*`) sum --- sommatoria usando funzionali sum xs = foldr (+) 0 xs sum xs = foldl (+) 0 xs isGreaterN:: Int -> [Int] -> bool --- tutti maggiori di n ? (usando funzionali) isGreaterN n xs = foldr (&&) True (map ( > n) xs) 12/7/2018
map, fold, filter: Applicazioni 2 lowerN:: Int -> [Int] -> [Int] --- tutti i termini minori di n (usando funzionali) lowerN n xs = filter (< n) xs allBooks:: [(autore,titolo,editore,anno)] -> [(autore,titolo,editore,anno)] --- tutti i book scritti da a successivi all’anno k allBooks books a xs = filter (\x->(((a==).fst) x) && (((k<).snd.snd.snd) x)) xs filter!!:: (a -> bool) -> [a] -> [Int] --- indici degli elementi che soddisfano filter!! p xs = 12/7/2018
Higher Order e Nuovi Costrutti Cosa succede in un linguaggio nel quale: I costrutti con i quali si esprimo i programmi sono entità (funzione): if_then_else:: bool -> a -> a -> a I valori calcolati dai programmi sono quelle stesse entità (funzione): Il linguaggio può essere esteso mantenendo proprietà formali cond:: [(bool,a)] -> a cond xs = a --- elemento prima coppia (b,a) il cui predicato b vale true iter:: … iter n f x = f (f … (f x)…) --- n volte f dropUntil:: … dropUntil p xs --- rimuove fino al primo che soddisfa p 12/7/2018
Proof: A | C --- reverse.reverese = id reverse (x:xs) = reverse xs ++ [x] [] ++ ys = ys (x:xs) ++ ys = x:(xs ++ ys) (1) (2) (3) (4) da A: segue Cxs: (reverse.reverse) xs = xs Proof: (Induzione sulla size delle liste) base: |xs|=0 => xs=[]=ys => reverse(reverse[]) = reverse [] = [] --- (1)(1) generale: induc-hyp: k: xs: |xs|<k => Cxs Sia xs: |xs|=k>0 => xs = x:zs per |zs|<k => => (reverse.reverse) xs = reverse(reverse xs) = reverse(reverse (x:zs)) = reverse(reverse zs ++ [x]) --- (2) = reverse [x] ++ (reverse(reverse zs)) --- lemma rev/++ = (reverse [x]) ++ zs --- induc-hyp. = [x] ++ zs --- lemma rev/[a] = x:[] ++ zs --- def: [a]a:[] = x:zs --- (4)(3) 12/7/2018
Esercizi Modulo Picture: rote90left Fib - stream di fibonacci (lineare + list_comprehension) Dimostrare che: rote90left :: Picture -> Picture rote90left p = let (u,v)=size p in if v==0 then [] else reverse((headR p):rote90left (tail p)) fib = let f = (0,1):[(v,u+v) | (u,v) <- f] in map fst f da A:{foldr f k [] = k ; foldr f k (x:xs) = f x (foldr f n xs)} segue C: foldr f k [x1,…,xn] = f x1 (f x2 (…(f xn k)…)) 12/7/2018
Esercizi Dimostrare che: Sia testo una rappresentazione di un testo come sequenza di linee: testo:: [[char]] occ - trova se una parola occorre in una linea occ parola = or.(map(==parola)) words - tutte le sottosequenze di una parola words n parola | n > (length parola) = [] | otherwise = (take n parola):(words (n-1) (drop 1 parola)) map (\n->take n parola) [0..(length parola)-1] Dimostrare che: da A:{foldl f k [] = k ; foldl f n (x:xs) = foldl f (f k x) xs} segue C: foldl f k [x1,…,xn] == f(f(…(f k x1)…)xn-1)xn 12/7/2018