Programación Funcional en Haskell Paradigmas de Lenguajes de Programación Facultad de Ciencias Exactas y Naturales Universidad de Buenos Aires 1 de Abril de 2014 Esquemas de recursión sobre listas Definamos las siguientes funciones sum :: Num a => [a] -> Int length :: [a] -> Int concat :: [[a]] -> [a] 2 / 14 Esquemas de recursión sobre listas Definamos las siguientes funciones sum :: Num a => [a] -> Int length :: [a] -> Int concat :: [[a]] -> [a] FoldR foldr :: (a -> b -> b) -> b -> [a] -> b foldr f z [] = .. foldr f z (x : xs) = .. sum = ? length = ? concat = ? 3 / 14 Esquemas de recursión sobre listas Definamos las siguientes funciones sum :: Num a => [a] -> Int length :: [a] -> Int concat :: [[a]] -> [a] FoldL foldl :: (b -> a -> b) -> b -> [a] -> b foldl f z [] = .. foldl f z (x : xs) = .. sum = ? length = ? concat = ? 4 / 14 Esquemas de recursión sobre listas Definamos las siguientes funciones insertar :: Ord a => a -> [a] -> [a] 5 / 14 Esquemas de recursión sobre listas Definamos las siguientes funciones insertar :: Ord a => a -> [a] -> [a] Recr recr :: (b -> [a] -> a -> b) -> b -> [a] -> b recr f z [] = .. recr f z (x : xs) = .. insert = ? 6 / 14 Ejercicios con foldr y foldl ¿Qué computan estas funciones? confundus :: [Bool] -> Bool confundus = foldr (&&) True spotify :: [a] -> [a] spotify = foldr (:) [] genkidama :: [a] -> [a] -> [a] genkidama xs ys = foldr (:) ys xs ayayay :: [a] -> [a] ayayay = foldl (flip (:)) [] colada :: [a] -> [a] colada = foldr1 max 7 / 14 Las difı́ciles! Definir en Haskell la función take, no vale recursión explı́cita take :: [a] -> n -> [a] 8 / 14 Las difı́ciles! Definir en Haskell la función take, no vale recursión explı́cita take :: [a] -> n -> [a] ¿Y la función zip? zip :: [a] -> [b] -> [(a,b)] 9 / 14 Tipos de datos Tipos de datos algebraicos. Determinados por la forma de cada elemento. abstractos. Determinados por las operaciones que manipulan sus elementos. Tipos algebraicos se acceden usando pattern matching están formados por constantes que son constructores, teniendo o no argumentos. se definen mediante la cláusula data 10 / 14 Folds sobre estructuras nuevas Definamos el tipo de los árboles estrictamente binarios data AEB a = | Hoja a Bin (AEB a) a (AEB a) Ejercicio Definir el esquema de recursión estructural y dar el tipo que permita recorrer esta estructura y luego definir las siguientes funciones: altura ramas #nodos #hojas espejo 11 / 14 Ejercicio Definir el esquema de recursión estructural para el siguiente tipo: data Num a => Polinomio a = | | | X Cte a Suma (Polinomio a) (Polinomio a) Prod (Polinomio a) (Polinomio a) Luego usar el esquema definido para escribir la función: evaluar::Num a => a -> Polinomio a -> a 12 / 14 Algo un poco más complejo... ¿o no? 1 Definir el tipo de datos RoseTree de árboles no vacı́os, donde cada nodo tiene una cantidad indeterminada de hijos. 2 Escribir el esquema de recursión estructural para RoseTree. Es importante escribir primero su tipo. Usando el esquema definido, escribir las siguientes funciones: 3 hojas, que dado un RoseTree, devuelve una lista con sus hojas ordenadas de izquierda a derecha, según su aparición en el RoseTree. 2 distancias, que dado un RoseTree, devuelve las distancias de su raı́z a cada una de sus hojas. 3 altura, que devuelve la altura de un RoseTree (la cantidad de nodos de la rama más larga). Si el RoseTree es una hoja, se considera que su altura es 1. 4 cantNodos, que devuelve la cantidad total de nodos del RoseTree. 1 13 / 14 ¿? ¿? ¿? ¿? ¿? ¿? ¿? ¿? ¿? ¿? ¿? ¿? ¿?