Herramientas de usuario

Herramientas del sitio


introalg:taller07_4

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
introalg:taller07_4 [2007/05/14 17:47] nicolaswintroalg:taller07_4 [2018/08/10 03:03] (actual) – editor externo 127.0.0.1
Línea 1: Línea 1:
 ====== Clase 4 ====== ====== Clase 4 ======
 +
 +
  
  
Línea 5: Línea 7:
 ===== Aplicación parcial (secciones) ===== ===== Aplicación parcial (secciones) =====
  
-Tomemos la siguente función Haskell que es una ligera variación de la que se encuentra en el problemario //esMultiplo//.+Tomemos la siguente función Haskell que es una ligera variación de //esMultiplo// que está en el problemario.
  
 <code> <code>
Línea 17: Línea 19:
  
 Esto lo podemos leer como que //esDivisor// es una función que toma un entero y **devuelve una función** de tipo //Int->Bool//. Esto lo podemos leer como que //esDivisor// es una función que toma un entero y **devuelve una función** de tipo //Int->Bool//.
-Esto es lo mismo que pasa en los ejercicios 5f, 5g y 5i del Práctico 5. +Esto es lo mismo que pasa en los ejercicios 5f, 5g y 5i del Práctico 5, y muestra que una función es un ciudadano de primera categoría en Haskell, puede ser devuelto como resultado de una función y también veremos que puede ser un parámetro de entrada
-De hecho le podemos preguntar a Hugs por el tipo de+ 
 +Para ganar confianza podemos preguntar a Hugs por el tipo de la aplicación parcial.
  
   Main> :t esDivisor 2   Main> :t esDivisor 2
Línea 28: Línea 31:
 <code> <code>
 esPar :: Int -> Bool esPar :: Int -> Bool
-esPar = esDivisor 2+esPar = esDivisor 2 x
 </code> </code>
  
 La función devuelve //True// si y solo si el entero es divisible por 2! La función devuelve //True// si y solo si el entero es divisible por 2!
-Notamos que esta definición es idéntica a esta versión **con argumentos**.+Notamos que esta definición es idéntica a esta versión **sin argumentos** que utiliza el mecanismo de secciones
 <code> <code>
 esPar' :: Int -> Bool esPar' :: Int -> Bool
-esPar' = esDivisor 2 x+esPar' = esDivisor 2
 </code> </code>
  
-Esta forma de denotar funciones se denomina [[http://en.wikipedia.org/wiki/Currying|currificación]], en honor al lógico [[http://es.wikipedia.org/wiki/Haskell_Curry|Haskell Curry]] ((Si si, el lenguaje Haskell se llama así por Haskell Curry.)).+Esta forma de escribir funciones se denomina [[http://en.wikipedia.org/wiki/Currying|currificación]], en honor al lógico [[http://es.wikipedia.org/wiki/Haskell_Curry|Haskell Curry]] ((Si si, el lenguaje Haskell se llama así por Haskell Curry.)).
  
 Este mecanismo de aplicación parcial de argumentos resulta muy elegante para escribir funciones. Este mecanismo de aplicación parcial de argumentos resulta muy elegante para escribir funciones.
Línea 59: Línea 62:
   [True,False,True,False]   [True,False,True,False]
  
-Le tiene que quedar claro que esta es una forma **elegante** y **compacta** de definir nuevas funciones a partir de otras, pero no es imprescindible. Por ejemplo, para el tercer ejemplo podemos definir la función auxiliar+Tiene que quedar claro que esta es una forma **elegante** y **compacta** de definir nuevas funciones a partir de otras, pero no es imprescindible. Por ejemplo, para el tercer ejemplo podemos definir la función auxiliar
  
 <code> <code>
Línea 71: Línea 74:
   [False,False,False,False]   [False,False,False,False]
  
 +=== Ejercicio ===
 +
 +  * Utilizando aplicación parcial en //( /= )//, definir la función //noEsCero :: Int -> Bool// que decide si un entero //x// es distinto a 0.
  
 ===== Generalización de las funciones vistas (map, filter, fold) ===== ===== Generalización de las funciones vistas (map, filter, fold) =====
 +
 +
  
  
Línea 87: Línea 95:
  
 ?No estamos ya cansados de escribir siempre lo mismo? ?No estamos ya cansados de escribir siempre lo mismo?
-Veamos solo algunas de las funciones de //tipo aplicación//, son todas idénticas, salvo por la **operación o función** que se aplica a cada elemento.+Las funciones de //tipo aplicación//, son todas idénticas, salvo por la **operación o función** que se aplica a cada elemento.
  
 <code> <code>
Línea 96: Línea 104:
  
 <code> <code>
-veintePorCiento : [Float] -> [Float] +veintePorCiento :: [Float] -> [Float] 
 veintePorCiento []     = [] veintePorCiento []     = []
 veintePorCiento (x:xs) = 0.2*x : veintePorCiento xs veintePorCiento (x:xs) = 0.2*x : veintePorCiento xs
Línea 118: Línea 126:
 Entonces **generalizemos** definiendo una función que toma como primer argumento la función que se aplicará a cada elemento de la lista. Entonces **generalizemos** definiendo una función que toma como primer argumento la función que se aplicará a cada elemento de la lista.
  
-Esta función es la primera que crearemos donde utilizamos **alto orden**, un nombre muy pomposo para algo bastante natural: **las funciones son un tipo más que puede ser tomado como parámetro y devuelto como resultado**.+Vemos nuevamente la aplicación del **alto orden**, un nombre muy pomposo para algo bastante natural: **las funciones son un tipo más que puede ser tomado como parámetro y devuelto como resultado**.
  
-Se dice que en Haskell las funciones son //ciudadanos de primera categoría//.+De nuevo, se dice que en Haskell las funciones son //ciudadanos de primera categoría//.
 Esto no ocurre en la mayoría de los //lenguajes imperativos// como C, C++, Pascal, Basic, etc. . Esto no ocurre en la mayoría de los //lenguajes imperativos// como C, C++, Pascal, Basic, etc. .
  
Línea 131: Línea 139:
 === Ejercicio === === Ejercicio ===
  
-  * Definir la función //mapNumero.f.xs//, //mapNumero : (Int -> Int) -> [Int] -> [Int]// que dada una función //f// y una lista de enteros //xs//, les aplica una función aritmética //f// y concatena el resultado en una lista. Ejemplo: //mapNumero.(+2).[0,1,2,3] = [2,3,4,5]//.+  * Definir la función //mapNumeros.f.xs//, //mapNumeros : (Int -> Int) -> [Int] -> [Int]// que dada una función //f// y una lista de enteros //xs//, les aplica una función aritmética //f// y concatena el resultado en una lista. Ejemplo: //mapNumeros.(+2).[0,1,2,3] = [2,3,4,5]//.
  
   probar con mapNumeros.(*2).[0,1,2,3], mapNumeros.absoluto.[-10,0,10].   probar con mapNumeros.(*2).[0,1,2,3], mapNumeros.absoluto.[-10,0,10].
 +
 +
 +
  
 ==== Filtros ==== ==== Filtros ====
Línea 140: Línea 151:
  
 <code> <code>
-esPar :: Int -> Bol +esPar :: Int -> Bool 
-esPar x `mod` == 0+esPar = esDivisor 2
  
 soloPares :: [Int] -> [Int] soloPares :: [Int] -> [Int]
Línea 160: Línea 171:
  
 Entonces plantemos el mismo tipo de ejercicio, una generalización que tome como primer parámetro un **predicado**, es decir una función que devuelve un booleano, que decidirá si cada elemento se conserva o se filtra. Entonces plantemos el mismo tipo de ejercicio, una generalización que tome como primer parámetro un **predicado**, es decir una función que devuelve un booleano, que decidirá si cada elemento se conserva o se filtra.
 +
 +=== Ejercicio ===
  
   * Definir la función //filtraNumeros.p.xs//, //filtraNumeros : (Int -> Bool) -> [Int] -> [Int]// que dada un predicado //p// y una lista de enteros //xs// devuelve la lista que contiene sólo aquellos números de //xs// que devuelven //True// en la predicado //p//. Ejemplo: //filtraNumeros.entre0y9.[11,4,37,3,10] = [4,3]//. Un ejemplo con algunas implicaciones más: //filtraNumeros.(esDivisor.3).[1,2,3,4,5,6,7,8,9,10] = [3,6,9]//.   * Definir la función //filtraNumeros.p.xs//, //filtraNumeros : (Int -> Bool) -> [Int] -> [Int]// que dada un predicado //p// y una lista de enteros //xs// devuelve la lista que contiene sólo aquellos números de //xs// que devuelven //True// en la predicado //p//. Ejemplo: //filtraNumeros.entre0y9.[11,4,37,3,10] = [4,3]//. Un ejemplo con algunas implicaciones más: //filtraNumeros.(esDivisor.3).[1,2,3,4,5,6,7,8,9,10] = [3,6,9]//.
  
   probar con filtraNumeros.entre0y9.[], filtraNumeros.entre0y9.[10,20,30].   probar con filtraNumeros.entre0y9.[], filtraNumeros.entre0y9.[10,20,30].
 +
 +
  
  
Línea 183: Línea 198:
  
 productoria :: [Int] -> Int productoria :: [Int] -> Int
-productoria []     0+productoria []     1
 productoria (x:xs) = producto x (productoria xs) productoria (x:xs) = producto x (productoria xs)
 </code> </code>
Línea 191: Línea 206:
 concatenaInt :: [[Int]] -> [Int] concatenaInt :: [[Int]] -> [Int]
 concatenaInt []       = [] concatenaInt []       = []
-concatenaInt (xs:xss) = xs ++ concatenaInt xss+concatenaInt (xs:xss) = (++) xs (concatenaInt xss)
 </code> </code>
  
Línea 225: Línea 240:
  
 <code> <code>
-mapa : (a -> b) -> [a] -> [b]+mapa :: (a -> b) -> [a] -> [b]
 mapa f []     = mapa f []     =
 mapa f (x:xs) = mapa f (x:xs) =
Línea 247: Línea 262:
 filtro p (x:xs) = filtro p (x:xs) =
 </code> </code>
 +
 +
  
 ==== Acumuladores (fold) ==== ==== Acumuladores (fold) ====
Línea 260: Línea 277:
  
 Detectamos: Detectamos:
-  * Un "*cero*" respecto a la acumulación (//True// es neutro de la conjunción).+  * Un "**cero**" respecto a la acumulación (//True// es neutro de la conjunción).
   * Una función de acumulación que a partir del elemento actual y lo acumulado en la llamada recursiva sobre //xs//, obtiene el valor de lo acumulado en el total //x:xs//.   * Una función de acumulación que a partir del elemento actual y lo acumulado en la llamada recursiva sobre //xs//, obtiene el valor de lo acumulado en el total //x:xs//.
  
-Podemos reescribirla de la siguiente manera par que la función de acumulación sea más explícita.+Podemos reescribirla de la siguiente manera para que la función de acumulación sea más explícita.
  
 <code> <code>
-ceroUnoyAnteriores :: Int -> Bool -> Bool +ceroUnoYAnteriores :: Int -> Bool -> Bool 
-ceroUnoyAnteriores x b = (x==0 || x==1) && b+ceroUnoYAnteriores x b = (x==0 || x==1) && b
  
 todos0y1' :: [Int] -> Bool todos0y1' :: [Int] -> Bool
 todos0y1' []     = True todos0y1' []     = True
-todos0y1' (x:xs) = ceroUnoyAnteriores x (todos0y1' xs)+todos0y1' (x:xs) = ceroUnoYAnteriores x (todos0y1' xs)
 </code> </code>
  
Línea 289: Línea 306:
  
 ===== Reescribiendo funciones usando map, fold y filter ===== ===== Reescribiendo funciones usando map, fold y filter =====
 +
 +
 +
  
 ==== Ejercicios ==== ==== Ejercicios ====
  
   * Escribir //duplicar// y //multiplicar// con //mapa//.   * Escribir //duplicar// y //multiplicar// con //mapa//.
 +    * Reescribir ambas utilizando aplicación parcial sobre //mapa// para evitar escribir el argumento de la lista.
 +  * Utilizando //mapa// escribir la función //largos :: [String] -> [Int]// que dada una lista de cadenas, retorna la lista con la longitud de cada una.
   * Escribir //soloPares// y //quitar0s// con //filtro//.   * Escribir //soloPares// y //quitar0s// con //filtro//.
 +    * Reescribir ambas utilizando aplicación parcial sobre //mapa// para evitar escribir el argumento de la lista.
 +  * Escribir //concatenaInt// usando //acumula//.
 +  * Escribir //sumatoria// usando aplicación parcial con //acumula//.
   * Escribir //paraTodoInt// usando //acumula//.   * Escribir //paraTodoInt// usando //acumula//.
   * Escribir //longitud// usando //acumula//.   * Escribir //longitud// usando //acumula//.
   * Escribir //reversa// usando //acumula//.   * Escribir //reversa// usando //acumula//.
-  * **DIFÍCIL** Escribir //mapa// y //filtro// usando //acumula//.+  * **(DIFÍCIL)** Escribir //mapa// y //filtro// usando //acumula//.
introalg/taller07_4.1179164852.txt.gz · Última modificación: 2018/08/10 03:03 (editor externo)