APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 1 de 20 More Create Blog Acceder APRENDIENDO HASKELLEJERCICIOS miércoles, 4 de mayo de 2016 Datos personales Aprendiendo Haskell- Ejercicios Diego Moreno - Consultor Tecnologico Ver todo mi perfil Archivo del blog Bienvenido ▼ 2016 (1) ▼ mayo (1) En el siguiente blog podra encontrar una breve introducciòn al mundo de haskell, para ello podra utilizar los ejercicios y soluciones colocandolos en practica y adentrarse a la nueva forma de programaciòn. Aprendiendo Haskell- Ejercicios Video introductorio ¿Que es Haskell y como se usa ? Curso de Haskell - Aula 01 - … ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::: 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 2 de 20 Querido estudiante en esta practica encontrara diferentes ejercicios, en donde podra colocar a prueba sus capacidades de logica matematica, para ello debera copiar en un bloc de notas la soluciòn de los talleres punto por punto para la ejecuciòn de estos en el software haskell 1. Redefinir las funciones del ejercicio 1 de la practica 2 usando foldr, map y filter. 2. Dada la función f = foldr (:) [] a) ¿Qué tipo tiene f? b) Dar una definición equivalente más simple de f 3. Definir las siguientes funciones utilizando funciones de alto orden cuando sea posible: a) pal, que determina si una cadena de caracteres es o no un palíndromo b) hache, que cuenta la cantidad de cadenas de caracteres que comienzan con h en una lista de cadenas c) longmed, que calcula la longitud promedio de las listas dentro de una lista de listas d) doblepos, que toma una lista de enteros y devuelve la lista de los dobles de los elementos positivos conservando el orden original e) adyac, que toma una lista y devuelve la lista de los pares ordenados de elementos adyacentes; por ejemplo, adyac [’a’,’b’,’c’,’d’] = [(’a’,’b’),(’b’,’c’),(’c’,’d’)] f) difPosAdy, que toma una lista de números y devuelva la lista de los pares ordenados de elementos adyacentes cuya diferencia es par g) remDups, que dada una lista devuelve una lista con los mismos elementos que la original pero eliminando todos aquellos valores que fuesen adyacentes e iguales, dejando una sola ocurrencia. Por ejemplo, remDups [2,2,0,2,3,3,0,0,1] = [2,0,2,3,0,1] 4. Definir las siguientes funciones: a) takeWhile’, que devuelve el segmento inicial más largo de una lista de elementos que verifica un predicado dado b) takeUntil, que devuelve el segmento inicial más largo de elementos que no verifica un predicado dado c) dropWhile’, que devuelve el segmento de una lista de elementos que comienza con el primer elemento que no verifica un predicado dado 5. Demostrar por inducción estructural sobre listas: a) map (f · g) = map f · map g b) map f (xs ++ ys) = (map f xs) ++ (map f ys) c) (map f) · concat = concat · (map (map f)) d) filter p (xs ++ ys) = (filter p xs) ++ (filter p ys) e) (filter p) · (filter q) = filter r where r x = (p x) && (q x) f) reverse (xs ++ ys) = reverse ys ++ reverse xs g) (filter p) · (map f) = (map f)·(filter (p · f)) h) map (map f) · (map (x:)) = map ((f x) :)·map (map f) i) concat · map concat = concat·concat 6. Definir una función perms :: [a] →[[a]] tal que perms xs sea la lista de todas las permutaciones de xs. Demostrar que map (map f) (perms xs) = perms (map f xs). ¿Para qué puede ser ´útil esta identidad? 7. Definir una función parts :: [a] →[[a]] tal que parts xs sea la lista de todas las sublistas de xs. (ys es una sablista de xs si existen listas as y bs tales que xs = as ++ ys ++ bs). Demostrar que map (map f) (parts xs) = parts (map f xs). ¿Para qué puede ser ´útil esta identidad? 8. a) Definir un predicado noDups :: [Int] →Bool tal que noDups xs = True solamente se cumpla cuando xs no tiene ningún elemento repetido. b) Definir una función sublist :: [Int] →[Int] → Bool de manera que solamente se cumpla sublist xs ys = True cuando xs es una sublista de ys. c) Definir una función removeDups :: [Int] →[Int] tal que removeDups xs sea una lista con exactamente los mismos elementos que xs pero sin repeticiones. d) Dar una condición suficiente sobre una funci´on f :: Int →Int para que map f (removeDups xs) = removeDups (map f xs) 9. Dar otra definición de la siguiente funci´on que no utilice la funci´on reverse: dropTrailingZeroes :: [Int] → [Int] dropTrailingZeroes = reverse · dropWhile (==0) · reverse 10. Definir una función splitAt :: Int →[a] → ([a],[a]) que satisfaga splitAt n xs = (take n xs, drop n xs) Dar otra definición en términos de foldr. 11. Definir la funci´on filter en términos de map y concat. 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 3 de 20 12. Definir una función tails :: [a] → [[a]] tal que tails = map reverse · inits · reverse 13. Dar definiciones usando foldr de las siguientes funciones: a) inits :: [a] →[[a]], como en la Practica 2; b) tails :: [a] →[[a]]; c) map :: (a →b) →[a] → [b]; 14. Demostrar el teorema de fusión por inducciión. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: SOLUCIÒN TALLER 4: [Ej. 1] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .................................... suma’ :: [Int] -> Int suma’ = foldr (+) 0 alguno’ :: [Bool] -> Bool alguno’ = foldr (||) False todos’ :: [Bool] -> Bool todos’ = foldr (&&) True codes’ :: [Char] -> [Int] codes’ = map ord restos’ :: Int -> [Int] -> [Int] restos’ = \n -> map (‘mod‘ n) cuadrados’ :: [Int] -> [Int] cuadrados’ = map (\x -> x*x) longitudes’ :: [[a]] -> [Int] longitudes’ = map (length) orden’ :: [(Int,Int)] -> [(Int,Int)] orden’ = filter (\x -> (fst(x) > snd(x))) pares’ :: [Int] -> [Int] pares’ = filter (\x -> x ‘mod‘ 2 == 0) masDe’ :: Int -> [[a]] -> [[a]] masDe’ = \n -> filter (\x -> length x > n) [Ej. 2] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .................................... f :: [a] -> [a] f = foldr (:) [] f’ :: [a] -> [a] f’ = id [Ej. 3] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .................................... pal :: [Char] -> Bool pal [] = True pal [a] = True pal (x:xs) = (x == head(reverse xs)) && pal (reverse(tail(reverse xs))) hache :: [[Char]] -> Int hache [] = 0 hache (xs:xss) = if head(xs) == ’h’ then 1 + hache xss else 0 + hache xss longmed :: [[a]] -> Int longmed xss = (foldr (+) 0 (map (length) xss)) ‘div‘ (length xss) doblepos :: [Int] -> [Int] 1 doblepos xs = map (^2) (filter (>0) xs) adyac :: [a] -> [(a,a)] adyac [] = [] adyac [x] = [] adyac (x:xs) = [(x,head(xs))] ++ adyac xs difPosAdy :: [Int] -> [(Int,Int)] difPosAdy [] = [] difPosAdy [x] = [] difPosAdy (x:xs) = if mod (x - head(xs)) 2 == 0 then [(x,head(xs))] ++ difPosAdy xs else difPosAdy xs remDups :: [Int] -> [Int] remDups [] = [] 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 4 de 20 remDups [x] = [x] remDups (x:xs) = if x /= head(xs) then [x] ++ remDups xs else remDups xs [Ej. 4] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .................................... takeWhile’ :: (a -> Bool) -> [a] -> [a] takeWhile’ f (x:xs) = if f x then x : (takeWhile f xs) else [] takeUntil :: (a -> Bool) -> [a] -> [a] takeUntil f (x:xs) = if (f x) == False then takeUntil f xs else [] dropWhile’ :: (a -> Bool) -> [a] -> [a] dropWhile’ f (x:xs) = if (f x) then dropWhile’ f xs else (x:xs) ....................................................................... ...................................... Algunas funciones y sus tipos map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = x : map f xs filter :: (a -> Bool) -> [a] -> [a] filter f [] = [] filter f (x:xs) = if x then x:filter xs else filter xs (.) :: (b -> c) -> (a -> b) -> a -> c (f.g) x = f(g x) (++) :: [a] -> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x:(xs++ys) (:) :: a -> [a] -> [a] (Primitiva) concat :: [[a]] -> [a] concat = foldr (++) [] reverse :: [a] -> [a] reverse [] = [] reverse (x:xs) = reverse xs ++ [x] 2 flip :: (b -> a -> c) -> a -> b -> c flip f x y = f y x foldl :: (b -> a -> b) -> b -> [a] -> b foldl f e [] = e foldl f e (x:xs) = foldl f (f e x) xs foldr :: (a -> b -> b) -> b -> [a] -> b foldr f e [] = e foldr f e (x:xs) = f x (foldr f e xs) [Ej. 5a] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... -*- map (f.g) = map f . map g -*- Probamos para el caso base [] map (f.g) [] = x def map [] map f . map g [] = x def . map f(map g []) = x def map map f [] = x def map [] .: map (f.g) [] = map f . map g [] -*- Suponemos que vale la h.i. map (f.g) xs = map f . map g xs -*- Probamos para (x:xs) map (f.g) (x:xs) = x def map (f.g) x : map (f.g) xs = x h.i. (f.g) x : map f . map g xs = x def map map f . (g x : map g xs) = x def map map f . (map g x:xs) 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 5 de 20 = x notacion map f . map g (x:xs) :. map (f.g) (x:xs) = map f . map g (x:xs) :. map (f.g) = map f . map g [Ej. 5b] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... -*- map f (xs ++ ys) = (map f xs) ++ (map f ys) 3 -*- Probamos el caso base para [] map f ([] ++ ys) = x def ++ map f ys (map f []) ++ (map f ys) = x def map [] ++ (map f ys) = x def ++ map f ys :. map f ([] ++ ys) = (map f []) ++ (map f ys) -*- Suponemos que vale la h.i. map f (xs ++ ys) = (map f xs) ++ (map f ys) -*- Probamos para (x:xs) map f ((x:xs) ++ ys) = x notacion map f (x:(xs ++ ys)) = x def map f x : map f (xs ++ ys) = x h.i. f x : (map f xs) ++ (map f ys) = x def map map f (x:xs) ++ (map f ys) :. map f (x:xs ++ ys) = (map f x:xs) ++ (map f ys) :. map f (xs ++ ys) = (map f xs) ++ (map f ys) [Ej. 5c] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... -*- (map f) . concat = concat . (map (map f)) -*- Veamos si los tipos coinciden (.) :: (b -> c) -> (a -> b) -> a -> c concat :: [[x]] -> [x] Si f :: x -> z map f :: [x] -> [z] .: a=[[x]], b=[x], c=[z] .: (map f) . concat :: [[x]] -> [z] (.) :: (b -> c) -> (a -> b) -> a -> c f :: x -> z map (map f) :: [[x]] -> [[z]] Si concat :: [[z]] -> [z] .: a=[[x]], b=[[z]], c=[z] .: concat . (map (map f)) :: [[x]] -> [z] -*- Probamos para [[]] 4 map f . (concat [[]]) = x def . map f (concat [[]]) = x def concat map f [] = x def map [] concat . (map (map f) [[]]) = x def . concat (map map(f) [[]]) = x def map concat [[]] = x def concat [] -*- Suponemos que vale la h.i. (map f) . concat xss = concat . (map (map f) xss) -*- Probamos para (xs:xss) 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 6 de 20 (map f) . concat (xs:xss) = x def . map f (concat (xs:xss)) = x def concat map f (xs ++ (concat xss)) = x def map map f xs ++ map f (concat xss) = x h.i. map f xs ++ concat . (map (map f) xss) = x def . map f xs ++ concat (map (map f) xss) = def concat concat ((map f) xs : map (map f) xss) = x def map concat (map (map f) (xs:xss)) = x def . concat . (map (map f) (xs:xss)) :. (map f) . concat (xs:xss) = concat . (map (map f) (xs:xss)) :. (map f) . concat = concat . (map (map f)) [Ej. 5d] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... -*- filter p (xs ++ ys) = (filter p xs) ++ (filter p ys) -*- Probamos para [] filter p ([] ++ ys) = filter p ys (filter p []) ++ (filter p ys) = [] ++ (filter p ys) 5 = filter p ys -*- Suponemos que vale la h.i. filter p (xs ++ ys) = (filter p xs) ++ (filter p ys) -*- Probamos para (x:xs) filter p ((x:xs) ++ ys) = (filter p (x:(xs ++ ys)) -*- Si p x = True = (x : filter p (xs ++ ys)) = x : ((filter p xs) ++ (filter p ys)) -- x h.i. = x : (filter p xs) ++ (filter p ys) = (filter p (x:xs)) ++ (filter p ys) -*- Si p x = False = filter p (xs ++ ys) -- x h.i. = (filter p xs) ++ (filter p ys) -- x def filter = (filter p (x:xs)) ++ (filter p ys) :. filter p ((x:xs) ++ ys) = (fiter p (x:xs)) ++ (filter p ys) :. filter p (xs ++ ys) = (filter p xs) ++ (filter p ys) [Ej. 5e] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... -*- (filter p) . (filter q) = filter r where r x = (p x) && (q x) -*- Probamos para x = [] (filter p) . (filter q) [] = filter p (filter q []) = filter p [] = [] filter r [] = [] -*- Suponemos valido para xs (filter p) . (filter q) xs = filter r xs filter p (filter q xs) = filter r xs -*- Probamos para x:xs (filter p) . (filter q) (x:xs) = filter p (filter q (x:xs)) -*- Si q x == True = filter p (x : filter q xs) 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 7 de 20 6 -*- Si p x == True = x : (filter p (filter q xs)) -- x h.i. = x : filter r xs = filter r where r x = (p x) && (q x) (x:xs) -*- Si p x == False = filter p (filter q xs) -- x h.i. = filter r xs = filter r where r x = (p x) && (q x) (x:xs) -*- Si p x == True = filter p (filter q xs) -- x h.i. = filter r xs = filter r where r x = (p x) && (q x) (x:xs) -*- Si q x == False = filter p (filter q xs) -- x h.i. = filter r xs = filter r where r x = (p x) && (q x) (x:xs) .: (filter p) . (filter q) (x:xs) = filter r where r x = (p x) && (q x) (x:xs) .: (filter p) . (filter q) = filter r where r x = (p x) && (q x) [Ej. 5f ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .................................... -*- reverse (xs ++ ys) = reverse ys ++ reverse xs -*- Probamos para [] reverse ([] ++ ys) = reverse ys reverse ys ++ reverse [] = reverse ys ++ [] = reverse ys -*- Probamos para (x:xs) reverse ((x:xs) ++ ys) = reverse (x:(xs ++ ys)) -- x def reverse = reverse (xs ++ ys) ++ [x] -- x h.i. = reverse ys ++ reverse xs ++ x -- x def reverse = reverse ys ++ reverse (x:xs) .: reverse ((x:xs) ++ ys) = reverse ys ++ reverse (x:xs) .: reverse (xs ++ ys) = reverse ys ++ reverse xs [Ej. 5g] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... 7 -*- (filter p) . (map f) = (map f) . (filter (p . f)) Nos fijamos si coinciden los tipos (.) :: (b -> c) -> (a -> b) -> a -> c Si f :: x -> y map f :: [x] -> [y] filter p :: [y] -> [y] .: p :: y -> Bool .: a=[x], b=[y], c=[y] .: (filter p) . (map f) :: [x] -> [y] (.) :: (b -> c) -> (a -> b) -> a -> c Si f :: x -> y p :: y -> Bool .: a=[x], b=[y], c=[Bool] .: (p . f) :: x -> Bool .: filter (p . f) :: [x] -> [x] map f :: [x] -> [y] (.) :: (b1 -> c1) -> (a1 -> b1) -> a1 -> c1 .: a1=[x], b1=[x], c1=[y] .: (map f) . (filter (p . f)) :: [x] -> [y] -*- Probamos para [] 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 8 de 20 (filter p) . (map f) [] = filter p (map f []) = filter p [] = [] (map f) . (filter (p . f)) [] = map f (filter (p . f) []) = map f [] = [] -*- Suponemos que vale (filter p) . (map f xs) = (map f) . (filter (p . f) xs) -*- Probamos para (x:xs) (filter p) . (map f) (x:xs) = filter p (map f (x:xs)) = filter p (f x : map f xs) -*- Si p (f x) == True = f x : filter p (map f xs) (*) -*- Si p (f x) == False = filter p (map f xs) (**) (map f) . (filter (p . f) (x:xs)) = map f (filter (p . f) (x:xs)) 8 -*- Si (p . f) x == True = map f (x : filter (p . f) xs) = f x : map f (filter (p . f) xs) -- x h.i = f x : (filter p) . (map f xs) = f x : filter p (map f xs) (*) = filter p (map f (x:xs)) = (filter p) . (map f (x:xs)) -*- Si (p . f) x == False = map f (filter (p . f) xs) -- x h.i. = (filter p) . (map f xs) = filter p (map f xs) (**) = filter p (map f (x:xs)) = (filter p) . (map f (x:xs)) .: (map f) . (filter (p . f) (x:xs)) = (filter p) . (map f (x:xs)) .: (filter p) . (map f) = (map f) . (filter (p . f)) [Ej. 5h] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... -*- map (map f) . (map (x:)) = map ((f x) :) map (map f) map ((map f (map (x:)))) = map ((f x) :) map (map f) (.) :: (b -> c) -> (a -> b) -> a -> c map (x:) :: [[x]] -> [[x]] map f :: [[x]] -> [[y]] f :: [x] -> [y] .: a = [[x]], b=[[x]], c=[[y]] map(f) . (map (x:)) :: [[x]] -> [[y]] -*- Probamos para el caso base [[]] map (map f) . (map (x:)) [[]] = map (map f (map (x:) [[]]) = map (map f [[x]] = [[f x]] map ((f x):) map (map f) [[]] = map ((f x):) map (map f [[]]) = map ((f x):) map [[]] = map ((f x):) [[]] = [[f x]] -*- Suponemos que vale para map (map f) . (map (x:)) xss = map ((f x) :) map (map f) xss -*- Probamos para (xs:xss) map (map f) . (map (x:)) (xs:xss) = map (map f (map (x:) xs:xss)) = map (map f (x:xs : map (x:) xss)) 9 = ([[f x]] : (map (map f) xs)) : (map f (map (x:) xss)) -- x h.i. = ([[f x]] : (map (map f) xs)) : map ((f x) :) map (map f) xss 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 9 de 20 = ([[f x]] : (map (map f) xs)) : map ((f x) :) (map (map f) xss) = (map (map f) x:xs) : map ((f x) :) (map (map f) xss) = ?????? [Ej. 5i] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .................................... -*- concat . map concat = concat . concat (.) :: (b -> c) -> (a -> b) -> a -> c concat :: [[x]] -> [x] .: map concat :: [[[x]]] -> [[x]] .: a = [[[x]]], b=[[x]], c=[x] .: concat . map concat :: [[[x]]] -> [x] (.) :: (b -> c) -> (a -> b) -> a -> c concat :: [[x]] -> [x] -- Sabemos que b no puede ser [x] por que tendriamos -- un error de tipo cuando se lo pasamos al primer concat, entonces Si concat :: [[[x]]] -> [[x]] .: a = [[[x]]], b=[[x]], c=[x] .: concat . concat :: [[[x]]] -> [x] -*- Probamos para [[[]]] concat . map concat [[[]]] = concat (map concat [[[]]]) = concat [[]] = [] concat . concat [[[]]] = concat (concat [[[]]]) = concat [[]] = [] -*- Suponemos que vale la h.i. concat . map concat xsss = concat . concat xsss -*- Probamos que vale para (xss:xsss) concat . map concat (xss:xsss) = concat (map concat (xss:xsss)) = concat (concat xss : map concat xsss) = concat (concat xss) ++ concat (map concat xsss) -- x h.i. = concat (concat xss) ++ concat . concat xsss = concat (concat xss ++ concat xsss) = concat (concat (xss:xsss)) = concat . concat (xss:xsss) .: concat . map concat (xss:xsss) = concat . concat (xss:xsss) 10 .: concat . map concat = concat . concat [Ej. 6] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .................................... -- Esta funcion va tomando cada elemtento y crea una lista -- te tuplas donde cada elemento tiene asociado sus listas a compararse -- Como se repiten los casos en que se hace -- a:(filter (a/=) [a,x1,..,xn]) == a:(filter (a/=) [x1,..,xn,a]) -- filtro los elementos unicos --- > perms [1,2,3] -- unicos(map fun2 concat[[(1,[1,2,3]),(1,[2,3,1]),(1,[3,2,1])],[(2,[1,2,3]),(2,[2,3,1]),...]]) -- unicos([[1,2,3],[1,2,3],[1,3,2],[2,1,3],[2,3,1],...]) -- [[1,2,3],[1,3,2],...] perms :: Eq a => [a] -> [[a]] perms ps = unicos(map fun2 (concat(map (\a -> fun a us (length(us))) us))) where fun2 (x,xs) = x:(filter (x/=) xs); us = unicos ps -- Esta funcion une un elemento con sus listas a comparar -- en los distintos ordenes posibles, donde n es el largo de la lista -- > fun 1 [1,2,3] 3 -- [(1,[1,2,3]),(1,[2,3,1]),(1,[3,1,2])] fun :: a -> [a] -> Int -> [(a,[a])] fun a (x:xs) 0 = [] fun a (x:xs) n = (a,x:xs):(fun a (xs++[x]) (n-1)) unicos :: Eq a => [a] -> [a] unicos [] = [] unicos (x:xs) = x:(unicos(filter (x/=) xs)) [Ej. 8] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 10 de 20 .................................... noDups :: [Int] -> Bool noDups [] = True noDups (x:xs) = (foldr (&&) True ((map (x/=) xs))) && noDups xs sublist :: [Int] -> [Int] -> Bool sublist [] ys = True sublist (x:xs) ys = (foldr (||) False ((map (x==) ys))) && sublist xs ys removeDups :: [Int] -> [Int] removeDups [] = [] removeDups (x:xs) = x:(removeDups(filter (x/=) xs)) f :: Int -> Int f x = x*x -- map f (removeDups xs) = removeDups (map f xs) [Ej. 9] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .................................... dropTrailingZeroes :: [Int] -> [Int] dropTrailingZeroes = reverse . dropWhile (==0) . reverse drop’ :: [Int] -> [Int] 11 drop’ [] = [] drop’ [0] = [] drop’ (x:xs) = x : drop’ (drop’ xs) [Ej. 10] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... splitAt :: Int -> [a] -> ([a],[a]) splitAt n xs = (take n xs, drop n xs) splitAt’ :: Int -> [a] -> ([a],[a]) splitAt’ _ [] = ([],[]) splitAt’ 0 xs = ([], xs) splitAt’ n (x:xs) = (x:ns,ms) where (ns,ms) = splitAt’ (n-1) xs sAt :: Int -> [a] -> ([a],[a]) sAt n xs = fst (foldr f (([],[]),length xs) xs) where f x ((as,bs),m) = if (m > n) then ((as,x:bs),m-1) else ((x:as,bs),m) [Ej. 11] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... filter :: (a -> Bool) -> [a] -> [a] filter f xs = concat(map (\x -> if map f x == [True] then x else []) (map (:[]) xs)) {Como concat :: [[a]] -> [a] separo los elementos de la lista en sublistas de 1 elemento. Despues, me fijo en cada sublista si se cumple f \x -> if map f x == [True] then x else [] transformando cada sublista donde no se cumple a la sublista []. Finalmente se concatenan todas las sublistas devolviendo una lista. Por ej: filter (>0) [1,-2,3] = concat [[1],[],[3]] = [1,3] -} [Ej. 12] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... import List tails :: [a] -> [[a]] tails = map reverse . inits . reverse tails’ :: [a] -> [[a]] tails’ [] = [[]] tails’ (x:xs) = (tails’ xs) ++ [(x:xs)] [Ej. 13] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... inits :: [a] -> [[a]] inits [] = [[]] inits xs = inits( reverse(tail(reverse xs)) ) ++ [xs] 12 inits’ :: [a] -> [[a]] inits’ xs = foldr (fun) [[]] (reverse xs) where fun x y = y ++ [(head (reverse y)) ++ [x]] tails :: [a] -> [[a]] tails [] = [[]] tails (x:xs) = (tails xs) ++ [(x:xs)] 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 11 de 20 tails’ :: [a] -> [[a]] tails’ xs = foldr (fun) [[]] xs where fun x y = y ++ [[x] ++ (head (reverse y))] map :: (a -> b) -> [a] -> [b] map f = foldr fun [] where fun x xs = f x : xs [Ej. 14] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ................................... Teorema de Fusion para foldr. Si f es estricta, con f a = b (1) y para todo x e y se tiene que f (g x y) = h x (f y) (2) entonces f . foldr g a = foldr h b (*) Demostracion -*- Caso base [] f . foldr g a [] = f (foldr g a []) = f (a) foldr h b [] =b -- x (1) = f (a) -*- Suponemos que vale para xs f . foldr g a xs = foldr h b xs -*- Probamos para (x:xs) f . foldr g a (x:xs) = f (foldr g a (x:xs)) = f (g x (foldr g a xs)) -- x (2) = h x (f (foldr g a xs)) -- x h.i. 13 = h x (foldr h b xs) = foldr h b (x:xs) .: f . foldr g a (x:xs) = foldr h b (x:xs) .: f . foldr g a = foldr h b (*) Taller 3 Practica 3 1. Inferir, de ser posible, los tipos de las siguientes funciones: a) modulus = sqrt · sum · map square; b) vmod[] = [] vmod(v:vs) = modulus v : vmod vs c) smap 0 f = map f smap (n+1) f = map (smap n f) 2. Dar el tipo de las funciones que se definen a continuación: a) hd (x:xs) = x; b) tl (x:xs) = xs; c) pred (x+1) = x; 3. ¿A qué valor reducen las siguientes expresiones, suponiendo evaluaciones lazy? a) pred 0; 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 12 de 20 b) tl [pred 0]; c) hd (tl [pred 0]); 4. Definir un tipo de Colores y una función mezclar que permita la combinación de los mismos. 5. a) Definir las operaciones de suma y producto módulo 2 para el tipo data DigBin = Cero |Uno b) Definir las operaciones de suma binaria, producto por dos, cociente y resto de la división por dos para el tipo: type NumBin = [Digbin] Donde convenimos que el primer elemento de las lista de dígitos es el digito menos significativo del número representado. c) Redefinir las funciones del ítem anterior, observando una convención opuesta. d) Definir funciones que multipliquen números binarios de acuerdo a las dos convenciones. 6. Un bag (o multiset) es una colecci´on de elementos. Cada elemento puede ocurrir un o más veces en el bag. Elija una representación eficiente para bags. Sería deseable que cada bag tenga una representación ´única. Definir las siguientes operaciones sobre bags, asegurándose de que aquellas que devuelvan bags lo hagan mediante una representación valida. a) list2bag, que toma una lista de elementos y devuelve un bag que contiene esos elementos. El número de ocurrencia de un elemento en la lista y en el bag resultante debe ser el mismo. b) bagEmpty, que devuelve True exactamente cuando el bag dado está vacío. c) bagCar, que devuelve su cardinalidad (cantidad total de ocurrencias de todos los elementos). d) bagElem, que devuelve verdadero si un elemento dado está en el bag dado; e) bagOccur, que devuelve True si dos bags tienen los mismos elementos con la misma cantidad de ocurrencias. f) bagEqual, que devuelve True si dos bags tienen los mismos elementos con la misma cantidad de ocurrencias. g) bagSubbag, que devuelve True si el primer bag es subbag del segundo; se dice que X es subbag de Y si cada elemento de X ocurre en Y al menos tantas veces como en X. h) bagInter, que toma dos bags y calcula el bag intersección. La intersección de dos bags X e Y contiene a todos los elementos comunes a X e Y con la menos cantidad posible de ocurrencias. i) bagSum, que calcula el bag unión de dos bags dados; el bag suma de los dos bags X e Y consiste de todos los elementos de X e Y con número de ocurrencias de suma de las ocurrencias en cada uno de estos bags. j) bagInsert, que toma un elemento y un bag y devuelve el bag con el elemento insertado. k) bagDelete, que toma un elemento y un bag, y devuelve el bag con el elemento borrado. 7. Definir las operaciones de unión e intersección de dos conjuntos y el predicado de pertenencia para conjuntos de elementos de tipo a representados. a) por comprensión (como predicado a → Bool); b) por extensión (como lista de elementos de a). SOLUCIÒN: Ej.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .............................. modulus :: [Float] -> Float modulus = sqrt.sum.map square square :: Float -> Float square x = x^2 vmod :: [[Float]] -> [Float] vmod [] = [] vmod (v:vs) = modulus v : vmod vs {smap 0 f = map f smap (n+1) f = map (smap n f) No se puede tipear la función smap en haskell por que su tipo depende de su argumento, en este caso, de (n+1). El caso base de smap devuelve una funcion g :: [a] -> [a] Si n = 0 smap devuelve 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 13 de 20 g’ :: [[a]] -> [[a]] Si n = 1 smap devuelve g’’ :: [[[a]]] -> [[[a]]] y asi sucesivamente. -} Ej. 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .............................. hd :: [a] -> a hd (x:xs) = x tl :: [a] -> [a] tl (x:xs) = xs pred :: Int -> Int pred (x + 1) = x Ej. 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .............................. ---> pred 0 Program error: pattern match failure: pred 0 Produce error porque no está definida la funcion pred para un n tal que n+1 = 0 pred 0 = x falta de pattern matching (no está definida para algún n tal que n+1=0) bottom ---> tl [pred 0] [] Devuelve la lista vacía por que la lista que se le pasa a tl es (x:xs) = (pred 0:[]) tl [pred 0] = x notacion tl (pred 0:[]) = x def de tl [] ---> hd (tl [pred 0]) Program error: pattern match failure: hd [] hd(tl [pred 0]) = x notacion hd(tl (pred 0:[]) = x def de tl hd([]) = x falta de PM -> indefinido bottom Ej. 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .............................. data Color = C Int Int Int deriving Show mezclar :: Color -> Color -> Color mezclar (C r1 g1 b1) (C r2 g2 b2) = C ((r1 + r2) ‘div‘ 2) ((g1 + g2) ‘div‘ 2) ((b1 + b2) ‘div‘ 2) Ej. 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .............................. data DigBin = Cero | Uno deriving (Show, Eq) {0+0=0 0+1=1 1+0=1 1 + 1 ,Acarreo 0 = 0, Acarreo 1 1 + 1 ,Acarreo 1 = 1, Acarreo 1 Por ej: 111 -> Acarreo 1010 1111 ---11001 -} -- Suma basica de binarios suma :: DigBin -> DigBin -> DigBin 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 14 de 20 suma Cero Cero = Cero suma Cero Uno = Uno suma Uno Cero = Uno suma Uno Uno = Cero -- Producto Modulo 2 pmod2 :: DigBin -> DigBin -> DigBin pmod2 Cero Cero = Cero pmod2 Cero Uno = Cero pmod2 Uno Cero = Cero pmod2 Uno Uno = Uno -- Esta funcion suma números binarios con el bit menos significativo como -- el primer elemento de la lista type NumBin = [DigBin] sumab_rev :: NumBin -> NumBin -> NumBin sumab_rev x y = suma’ x y Cero -- Las demás no las defino xq no tengo ganas. -- Ahora usando la convención standard, donde el primer elemento de la lista es el -- bit mas significativo. -- Como la suma es de derecha a izquierda primero doy vuelta el orden de la lista -- si no empieza sumando del bit mas significativo al menos significativo y es al -- revés. Antes de devolverla vuelvo a dar vuelta el resultado para que se pueda -- leer como número binario. sumab :: NumBin -> NumBin -> NumBin sumab x y | length x == length y = reverse (suma’ (reverse x) (reverse y) Cero) | otherwise = error ("Los números binarios no tienen la misma cantidad de bits") suma’ :: NumBin -> NumBin -> DigBin -> NumBin suma’ [] [] acarreo | acarreo == Cero = [] | acarreo == Uno = Uno:[] suma’ [] (x:xs) acarreo = suma’ (x:xs) [] acarreo suma’ (x:xs) [] acarreo | x == Cero && acarreo == Cero = Cero :(suma’ xs [] Cero) | x == Uno && acarreo == Cero = Uno :(suma’ xs [] Cero) | x == Cero && acarreo == Uno = Cero :(suma’ xs [] Uno) | x == Uno && acarreo == Uno = Cero :(suma’ xs [] Uno) suma’ (x:xs) (y:ys) acarreo | x == Cero && y == Cero && acarreo == Cero = Cero :(suma’ xs ys Cero) | x == Cero && y == Uno && acarreo == Cero = Uno :(suma’ xs ys Cero) | x == Uno && y == Cero && acarreo == Cero = Uno :(suma’ xs ys Cero) | x == Cero && y == Cero && acarreo == Uno = Uno :(suma’ xs ys Cero) | x == Cero && y == Uno && acarreo == Uno = Cero :(suma’ xs ys Uno) | x == Uno && y == Cero && acarreo == Uno = Cero :(suma’ xs ys Uno) | x == Uno && y == Uno && acarreo == Cero = Cero :(suma’ xs ys Uno) | x == Uno && y == Uno && acarreo == Uno = Uno :(suma’ xs ys Uno) prodx2 :: NumBin -> NumBin prodx2 x = sumab x x {Vamos a usar la resta, sumando el complemento a 2: El complemento a 1 de un valor binario se obtiene invirtiendo el estado de todas sus cifras, incluyendo los ceros a la izquierda hasta completar la capacidad del registro. Por ejemplo, el valor 10011 en un registro de 8 bits (cifras) sería 00010011 y su complemento a 1 sería 11101100. El complemento a 2 de un valor binario se obtiene sumando 1 al complemento a 1. Por ejemplo, el complemento a 2 de 10011 (el mismo anterior) sería 11101100 + 1 = 11101101. Como restar sumando: El complemento a 2 de un número binario se puede considerar directamente su equivalente negativo. Por lo tanto, para hacer la resta a - b = ¿x? basta con calcular el resultado "x" (sin olvidar el tamaño del registro que se utilice) como: x = a + (complemento a 2 de b) Utilizando el Complemento a dos. La resta de dos n´umeros binarios puede obtenerse sumando al minuendo el complemento a dos del sustraendo. Veamos algunos ejemplos: Hagamos la siguiente resta, 91 - 46 = 45, en binario: 1011011 1011011 -0101110 C246 = 1010010 +1010010 -------- -------0101101 10101101 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 15 de 20 En el resultado nos sobra un bit, que se desborda por la izquierda. Pero, como el n´umero resultante no puede ser más largo que el minuendo, el bit sobrante se desprecia. -} complemento_1 :: NumBin -> NumBin complemento_1 [] = [] complemento_1 (x:xs) | x == Cero = Uno : complemento_1 xs | x == Uno = Cero : complemento_1 xs complemento_2 :: NumBin -> NumBin complemento_2 x = sumab (complemento_1 x) (binUnoConZeros (length x)) -- Esta funcion genera el numero binario uno de n bits [Cero,Cero,...,Uno] -- para poder hacer el complemento a 2 binUnoConZeros :: Int -> NumBin binUnoConZeros 1 = [Uno] binUnoConZeros n = Cero : binUnoConZeros (n-1) restab :: NumBin -> NumBin -> NumBin restab x y | length(sumab x (complemento_2 y)) > length x = tail(sumab x (complemento_2 y)) | otherwise = sumab x (complemento_2 y) -- La división x 2 es un shift a la derecha, descartando el último bit -- 1010 / 2 = 0101 cocientebx2 :: NumBin -> NumBin cocientebx2 x = Cero : reverse(tail(reverse x)) -- El resto de la división x 2 es el bit que desaparecería si hiciésemos -- un shift a la derecha restococientebx2 :: NumBin -> DigBin restococientebx2 x = head(reverse x) Ej. 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .............................. -- Defino los Bags como una lista de tuplas -- [(elemento, Numero de apariciones de un elemento)] type Bag a = [(a,Int)] --list2bag :: [a] -> Bag a list2bag [] = [] list2bag (x:xs) = bagInsert x (list2bag xs) --bagInsert :: a -> Bag a -> Bag a bagInsert a [] = [(a,1)] bagInsert a ((b,n):xs) = if a == b then (b,n+1):xs else (b,n):bagInsert a xs bagEmpty x = if x == [] then True else False bagCar [] = 0 bagCar ((b,n):xs) = n + bagCar xs bagElem a [] = False bagElem a ((b,n):xs) = if a == b then True else bagElem a xs bagOcurr a [] = False bagOcurr (a,n) ((b,m):xs) = if a == b && n==m then True else bagOcurr (a,n) xs bagEqual [] [] = True bagEqual _ [] = False bagEqual [] _ = False bagEqual ((a,n):xs) ((b,m):ys) = if a==b && n==m then True && bagEqual xs ys else False bagSubbag [] [] = True bagSubbag _ [] = False bagSubbag [] _ = True bagSubbag ((a,n):xs) ((b,m):ys) = if a==b && n<=m then True && bagSubbag xs ys else bagSubbag ((a,n):xs) ys bagminEnbag [] [] = 0 bagminEnbag _ [] = 0 bagminEnbag [] _ = 0 bagminEnbag [(a,n)] ((b,m):ys) = if a==b then min n m else bagminEnbag [(a,n)] ys bagInter [] _ = [] bagInter ((a,n):xs) ((b,m):ys) = if x > 0 then (a, x):bagInter xs ((b,m):ys) 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 16 de 20 else bagInter xs ((b,m):ys) where x = bagminEnbag [(a,n)] ((b,m):ys) insertNveces a 1 ys = bagInsert a ys insertNveces a n ys = bagInsert a (insertNveces a (n-1) ys) bagSum [] ys = ys bagSum ((a,n):xs) ys = bagSum xs (insertNveces a n ys) bagDelete _ [] = [] bagDelete (a,n) ((b,m):ys) | a/=b = (b,m):bagDelete (a,n) ys | a==b && n>=m = ys | a==b && n<m = (b,m-n):ys TALLER 2 1. Sin usar funciones de alto orden ni funciones definidas en el preludio, defina recursivamente las siguientes funciones y determine su tipo más general: a) suma, que suma todos los elementos de una lista de números b) alguno, que devuelve True si algún elemento de una lista de valores booleanos es True, y False en caso contrario c) todos, que devuelve True si todos los elementos de una lista de valores booleanos son True y False en caso contrario d ) codes, que dada una lista de caracteres, devuelve la lista de sus ordinales e) restos, que calcula la lista de los restos de la división de los elementos de una lista de números dada por otro número dado f) cuadrados, que dada una lista de números, devuelva la lista de sus cuadrados g) longitudes, que dada una lista de listas, devuelve la lista de sus longitudes h) orden, que dada una lista de pares de números, devuelve la lista de aquellos pares en los que la primera componente es menor que el triple de la segunda i ) pares, que dada una lista de enteros, devuelve la lista de los elementos pares j) letras, que dada una lista de caracteres, devuelve la lista de aquellos que son letras (minúsculas o mayúsculas) k) masDe, que dada una lista de listas xss y un número n, devuelve la lista de aquellas listas de xss con longitud mayor que n 2. Indicar bajo que suposiciones pueden evaluarse las siguientes ecuaciones. Para aquellas que puedan evaluarse indicar si son verdaderas y en caso de no serlo modificar su lado derecho para que resulten verdaderas: a) [[]] ++ xs = xs b) [[]] ++ xs = [xs] c) [[]] ++ xs = [] : xs d) [[]] ++ xs = [[],xs] e) [[]] ++ [xs] = [[],xs] f) [[]] ++ [xs] = [xs] g) [] ++ xs = [] : xs h) [] ++ xs = xs i) [xs] ++ [] = [xs] j) [xs] ++ [xs] = [xs,xs] k) [] : xs = xs 3. Demostrar la siguiente propiedad: sum xs ≤ length xs ∗ maxl xs, sabiendo que xs es una lista de números naturales y que maxl [] = 0 sum [] = 0 maxl (x:xs) = x ‘max‘ maxl xs sum (x:xs) = x + sum xs 4. Defina una función all :: (c → Bool) →[a] → Bool tal que all p xs = True exclusivamente en el caso que todos los elementos de xs satisfagan el predicado p. 5. Defina las siguientes funciones: a) isPrime :: Int →Bool, que decide si un número positivo es o no primo. b) primes :: Int →[Int], tal que primes n es la lista de los números primos menores o iguales que n para n > 0. c) product :: [Int] →Int, tal que product xs es el producto de todos los elementos de xs. N.B: Recuerde que un producto con ningún factor vale 1. d) factors :: Int →[Int] tal que • all isPrime (factors x) = True • product · factors = id para cada entero positivo x. 6. Demostrar las siguientes propiedades: a) curry · uncurry = id b) uncurry · curry = id 7. Se puede definir la sintaxis de un lenguaje sencillo en forma inductiva de la siguiente manera: El conjunto de términos es el menor conjunto τ tal que: 1. {true, false, 0} ⊆ τ ; 2. if t1 ∈ τ , then {succ t1, pred t1, iszero t1} ⊆ τ ; 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 17 de 20 3. if t1 ∈ τ , t2 ∈ τ , t3 ∈ τ , then if t1 then t2 else t3 ∈ τ . Otra forma de definir el mismo conjunto de t´erminos es un estilo más ”‘concreto”’ que proporciona una manera explicita de generar los elementos de τ : Para cada natural i, se define un conjunto Si como sigue: S0 = Si+1 = {true, false, 0} ∪ {succ t1, pred t1, iszero t1 | t1 ∈ Si} ∪ {if t1 then t2 else t3 | t1, t2, t3 ∈ Si} Finalmente: S = S i Si . a) ¿Cuál es la cantidad de elementos de S3?. b) Mostrar que los conjuntos Si son acumulativos, es decir, que para cada i tenemos Si ⊆ Si+1. Practica 2 2006 Pagina 2 Análisis de Lenguajes de Programación II c) Demostrar que τ = S. d) ¿Es posible generalizar este ´ultimo estilo de definición para cualquier definición inductiva? 8. a) Sean xs = [1,2,3], ys = [4,5,6] y zs = [7,8,9], reduzca las siguientes expresiones usando la definición recursiva de ++ : • xs ++ (ys ++ zs); • (xs ++ ys) ++ zs; b) ¿Cuál de las dos expresiones se evalúa en menos pasos? c) ¿El operador ++ debería asociar a izquierda o a derecha? d) ¿Que asociatividad se declara para ++ en el preludio de Haskell? Solución Taller 2 suma :: [Int] -> Int suma [] = 0 suma (x:xs) = x + suma xs suma’ :: [Int] -> Int suma’ = foldr (+) 0 alguno :: [Bool] -> Bool alguno [] = False alguno (x:xs) = x || alguno xs alguno’ :: [Bool] -> Bool alguno’ = foldr (||) False todos :: [Bool] -> Bool todos [] = True todos (x:xs) = x && todos xs todos’ :: [Bool] -> Bool todos’ = foldr (&&) True codes :: [Char] -> [Int] codes [] = [] codes (x:xs) = ord(x):codes xs codes’ :: [Char] -> [Int] codes’ = map ord restos :: Int -> [Int] -> [Int] restos n [] = [] restos n (x:xs) = (x ‘mod‘ n):restos n xs restos’ :: Int -> [Int] -> [Int] restos’ = \n -> map (‘mod‘ n) cuadrados :: [Int] -> [Int] cuadrados [] = [] cuadrados (x:xs) = (x*x):cuadrados xs cuadrados’ :: [Int] -> [Int] cuadrados’ = map (\x -> x*x) longitudes :: [[a]] -> [Int] longitudes [] = [] longitudes (xs:xss) = length(xs):longitudes xss longitudes’ :: [[a]] -> [Int] longitudes’ = map (length) orden :: [(Int,Int)] -> [(Int,Int)] 1 orden [] = [] orden (x:xs) = if fst(x) > snd(x) then x : orden xs else orden xs orden’ :: [(Int,Int)] -> [(Int,Int)] orden’ = filter (\x -> (fst(x) > snd(x))) 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 18 de 20 pares :: [Int] -> [Int] pares [] = [] pares (x:xs) = if mod x 2 == 0 then x:pares xs else pares xs pares’ :: [Int] -> [Int] pares’ = filter (\x -> x ‘mod‘ 2 == 0) masDe :: Int -> [[a]] -> [[a]] masDe n [] = [] masDe n (xs:xss) = if length(xs) > n then xs : masDe n xss else masDe n xss masDe’ :: Int -> [[a]] -> [[a]] masDe’ = \n -> filter (\x -> length x > n) [Ej. 2] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...................... a) Si xs = [[a]] -Falso - [[]] ++ xs = [[],xs] b) Si xs = [[a]] -Falso - [[]] ++ xs = [[],xs] c) Si xs = [[a]] -False - [[]] ++ xs = [[],xs] d) Si xs = [[a]] -Verdadero e) Si xs = [a] - Verdadero f) Si xs = [a] - Falso -[[]] ++ xs = [[],xs] g) Si xs = [a] - Falso - [] ++ xs = xs h) Si xs = [a] - Verdadero i) Si xs = a - Verdadero j) Para todo xs -Verdadero k) Si xs = [[a]] - Verdadero - [] : xs = xs [Ej. 3] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...................... (1) -> maxl [] = 0 (2) -> maxl (x:xs) = x ‘max‘ maxl xs (3) -> sum [] = 0 (4) -> sum (x:xs) = x + sum xs Vamos a demostrar que sum xs <= length xs * maxl xs = x_1 + sum x_2 + ... + sum x_n <= n * max { x_1, ..., x_n } = [Ej. 4] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...................... -- Esta funcion hace lo que pide el enunciado -- no se puede hacer si el tipo es -- (c -> Bool) -> [a] -> Bool -- por que la funcion que toma como argumento 2 -- tiene que ser si o si (a -> Bool) para examinar -- los elementos de la lista y devolver algo -- En este caso usamos la funcion positivo -- para que siempre se satisfaga el predicado p all’ :: (a -> Bool) -> [a] -> Bool all’ p [] = True all’ p (x:xs) = (p x) && (all’ p xs) -- Esta funcion es de tipo -- (c -> Bool) -> [a] -> Bool -- pero no hace lo que pide el enunciado all’’ :: (c -> Bool) -> [a] -> Bool all’’ p (x:xs) = True positivo :: c -> Bool positivo c = True [Ej. 5] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...................... isPrime :: Int -> Bool isPrime x = primeDiv x (x-1) primeDiv :: Int -> Int -> Bool primeDiv 1 0 = True primeDiv x 1 = True primeDiv x y = ((x ‘mod‘ y) > 0) && (primeDiv x (y-1) ) -- isPrime2 es mucho mas eficiente que isPrime -- para descartar numeros que no son primos isPrime2 :: Int -> Bool isPrime2 x = primeDiv2 x 2 primeDiv2:: Int -> Int -> Bool primeDiv2 x y | x == 1 = True | x == y = True | ((x ‘mod‘ y) == 0) = False | otherwise = (True && primeDiv2 x (y+1)) -- Se comprueba buscando los primeros n primos primes :: Int -> [Int] 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 19 de 20 primes x = listPrimos isPrime x 0 [] primes2 :: Int -> [Int] primes2 x = listPrimos isPrime2 x 0 [] listPrimos :: (Int -> Bool) -> Int -> Int -> [Int] -> [Int] listPrimos f a b c | a == b = if f b == True then c++[b] else c | otherwise = if f b == True then listPrimos f a (b+1) c++[b] 3 else listPrimos f a (b+1) c -- no se puede usar el nombre "product" produc :: [Int] -> Int produc = foldr (*) 1 factors :: Int -> [Int] factors x = buscarFactors x 2 [1] buscarFactors :: Int -> Int -> [Int] -> [Int] buscarFactors a b c | a == 1 = [1] | a == b = if (isPrime2 b) == True then c ++ [b] else c | otherwise = if ((a ‘mod‘ b) == 0) && (isPrime2 b) == True then buscarFactors (div a b) 2 c ++ [b] else buscarFactors a (b+1) c [Ej. 8] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...................... (0) - jj :: [a] -> [a] -> [a] (1) - [] ‘jj‘ ys = ys (2) - (x:xs) ‘jj‘ ys = x : (xs ‘jj‘ ys) xs = [1,2,3] ys = [4,5,6] zs = [7,8,9] [1,2,3] ++ ([4,5,6] ++ [7,8,9]) = x notacion (1:(2:(3:[]))) ++ ((4:(5:(6:[]))) ++ (7:(8:(9:[])))) = x def ++ 2 1:(2:(3:[]))) ++ (4:((5:(6:[]))) ++ (7:(8:(9:[])))) = x def ++ 2 1:(2:(3:[]))) ++ (4:(5:(6:([] ++ (7:(8:(9:[]))))))) = x def ++ 1 1:(2:(3:[]))) ++ (4:(5:(6:(7:(8:(9:[])))))) = x def ++ 2 1:(2:(3:([] ++ (4:(5:(6:(7:(8:(9:[]))))))))) = x def ++ 1 1:(2:(3:(4:(5:(6:(7:(8:(9:[])))))))) = x notacion [1,2,3,4,5,6,7,8,9] ([1,2,3] ++ [4,5,6]) ++ [7,8,9] = x notacion ((1:(2:(3:[]))) ++ (4:(5:(6:[])))) ++ (7:(8:(9:[]))) = x def ++ 2 (1:(2:(3:[] ++ (4:((5:(6:[]))))))) ++ (7:(8:(9:[]))) = x def ++ 2 (1:(2:(3:([] ++ (4:(5:(6:[]))))))) ++ (7:(8:(9:[]))) Publicado por Diego Moreno - Consultor Tecnologico en 19:13 No hay comentarios: Publicar un comentario Enter your comment... Comment as: Publicar Liceo Libertad inscripciones Plan 94 (Go Sign out Notify me Vista previa Inicio 1/10/2021 8:40 APRENDIENDO HASKELL-EJERCICIOS: Aprendiendo Haskell- Ejerc... http://aprendiendohaskell.blogspot.com/2016/05/aprendiendo-haskell-eje... 20 de 20 Suscribirse a: Enviar comentarios (Atom) Tema Sencillo. Con la tecnología de Blogger. 1/10/2021 8:40