introalg:taller08_1
Diferencias
Muestra las diferencias entre dos versiones de la página.
Próxima revisión | Revisión previa | ||
introalg:taller08_1 [2008/03/18 21:11] – creado laura | introalg:taller08_1 [2018/08/10 03:03] (actual) – editor externo 127.0.0.1 | ||
---|---|---|---|
Línea 1: | Línea 1: | ||
- | ====== | + | ====== |
- | ====== Introducción a los Algoritmos 2008 ====== | + | |
+ | ===== Introducción al uso de Hugs===== | ||
+ | [[http:// | ||
+ | Durante este taller escribiremos, | ||
- | ===== Clases ===== | + | A Hugs se lo invoca desde la //línea de comandos// o picando sobre el icono en nuestro entorno gráfico. |
+ | Una vez que el intérprete está activo, la pantalla se presenta con un //prompt// a la espera de **expresiones** a ser evaluadas o **comandos**. | ||
- | |Abr 8-10 | [[IntroAlg: | + | |
- | |Abr 15-17 | [[IntroAlg: | + | |
- | |Abr 22-24 | [[IntroAlg: | + | |
- | |May 29-1 | | + | ||___|| ||__|| ||__|| |
- | |May 6-8 | + | ||---|| ___|| World Wide Web: http:// |
- | |May 13-15 | [[IntroAlg: | + | || |
- | |May 20-22 | | + | || |
- | |May 27-29 | [[IntroAlg: | + | |
- | |Jun 3-5 | + | |
- | |Jun 10-12 | **Parcialito 2** | Funciones recursivas | + | |
- | |Jun 17 | [[IntroAlg:taller08_7|La Guinda]] | la guinda del taller | | + | Type :? for help |
+ | Hugs.Base> | ||
- | ===== Problemas ===== | + | De este modo Hugs se convierte en una calculadora, |
- | * [[introalg:problemas08|Problemario del taller]], con todos los problemas que vas a resolver en el taller de Haskell. | + | Gracias al [[http:// |
- | * [[introalg: | + | |
+ | 42 | ||
+ | Hugs.Base> | ||
+ | False | ||
+ | Hugs.Base> | ||
+ | False | ||
+ | Hugs.Base> | ||
+ | [2, | ||
+ | Hugs.Base> reverse " | ||
+ | "daba le arroz al a zorra elabad" | ||
- | ===== Programas ===== | + | Podemos salir del intérprete Hugs con '' |
- | Para los usuarios de Windows y [[http:// | + | Hugs.Base> |
- | Las principales distribuciones Linux (Debian, Ubuntu, Fedora y Gentoo) incluyen Hugs como un paquete de instalación. \\ | + | |
- | En Windows tenemos | + | [laura@azul Taller]$ |
- | ===== Bibliografía ===== | + | Así volvemos al modo normal de la computadora. |
- | * José Gallardo, Paco Gutiérrez | + | |
- | | + | Para poder dar nuevas definiciones |
- | | + | |
- | * Jose E. Labra G., [[http://horru.lsi.uniovi.es/~labra/FTP/IntHaskell98.pdf|Introducción al lenguaje Haskell]], Universidad | + | Un programa funcional |
- | * Simon Thompson, [[http://www.cs.kent.ac.uk/people/staff/sjt/craft2e/|Haskell The Craft of Functional Programming]], 2da edición, Addison-Wesley, 1999. | + | |
- | * Mucho material en inglés de [[http://haskell.org/haskellwiki/Books_and_tutorials# | + | Como ejemplo, vamos a ver todo el proceso |
+ | |||
+ | sgn :: Int → Int | ||
+ | -- dado un entero x, //sgn// retorna su signo, de la siguiente forma: | ||
+ | -- retornará 1 si x es positivo, -1 si es negativo y 0 en cualquier otro caso. | ||
+ | |||
+ | Para crear un //script// basta con invocar el comando para editar un (nuevo) archivo '': | ||
+ | |||
+ | | ||
+ | |||
+ | Una posible solución para el problema de la función signo es la siguiente: | ||
+ | |||
+ | sgn :: Int -> Int | ||
+ | sgn x | 0< | ||
+ | | x< | ||
+ | | x=0 = 0 | ||
+ | |||
+ | |||
+ | Luego de guardar el programa, hay cargarlo para que el intérprete Hugs pueda empezar a usar la nueva función que hemos creado. | ||
+ | |||
+ | Hugs.Base> | ||
+ | ERROR " | ||
+ | |||
+ | Pero el intérprete indica un error! Por qué? Porque " | ||
+ | |||
+ | Las traducciones de los símbolos son más o menos directas, de todas formas preparamos una tabla de [[http://cs.famaf.unc.edu.ar/introalg/PDF/traduccion.pdf|Traducción de "Cálculo de Programas" | ||
+ | |||
+ | Para solucionar el error, volvemos a editar el script con '': | ||
+ | |||
+ | sgn :: Int -> Int | ||
+ | sgn x | 0< | ||
+ | | x< | ||
+ | | x==0 = 0 | ||
+ | |||
+ | |||
+ | Luego de guardar el programa, hay que **volver a cargarlo** para que el intérprete pueda usar la función corregida, si no lo cargamos, el intérprete se queda en el estado anterior, en el que no tenía la función porque ésta tenía un error. | ||
+ | |||
+ | Hugs.Base> | ||
+ | Main> | ||
+ | |||
+ | Ahora sí, la función es correcta y por ello el intérprete nos muestra el prompt '' | ||
+ | |||
+ | Podemos probar la nueva función con //casos de test// para ganar confianza en su **corrección**. | ||
+ | |||
+ | Main> sgn 1 | ||
+ | 1 | ||
+ | Main> sgn 0 | ||
+ | 0 | ||
+ | Main> sgn -1 | ||
+ | ERROR - Cannot infer instance | ||
+ | *** Instance | ||
+ | *** Expression : sgn - 1 | ||
+ | |||
+ | Main> sgn (-1) | ||
+ | -1 | ||
+ | Main> sgn 123123123123 | ||
+ | |||
+ | Program error: arithmetic overflow | ||
+ | |||
+ | Main> sgn 123123123 | ||
+ | 1 | ||
+ | Main> sgn 1.1 | ||
+ | ERROR - Cannot infer instance | ||
+ | *** Instance | ||
+ | *** Expression : sgn 1.1 | ||
+ | |||
+ | Main> sgn (-1 | ||
+ | ERROR - Syntax error in expression (unexpected end of input) | ||
+ | |||
+ | Main> sgn "hola" | ||
+ | ERROR - Type error in application | ||
+ | *** Expression | ||
+ | *** Term : " | ||
+ | *** Type : String | ||
+ | *** Does not match : Int | ||
+ | |||
+ | Main> map sgn [-10..10] | ||
+ | [-1, | ||
+ | |||
+ | |||
+ | Notamos los distintos tipos de errores que se producen por problemas de | ||
+ | * Precedencia ('' | ||
+ | * Tipos ('' | ||
+ | * Sintaxis ('' | ||
+ | |||
+ | |||
+ | ===== Inferencia de tipos ===== | ||
+ | |||
+ | Haskell es un lenguaje tipado, es decir, todos los datos pertenecen a una clase o tipo de datos. Hugs tiene una maquinaria para //inferir// tipos, tanto los declarados | ||
+ | |||
+ | | ||
+ | sgn :: Int -> Int | ||
+ | |||
+ | Como expresiones en general | ||
+ | |||
+ | Main> :t 1 + 2.1 | ||
+ | 1 + 2.1 :: Fractional a => a | ||
+ | |||
+ | Main> :t 1+ sqrt 64 | ||
+ | 1 + sqrt 64 :: Floating a => a | ||
+ | |||
+ | Main> :t 1+ " | ||
+ | ERROR - Cannot infer instance | ||
+ | *** Instance | ||
+ | *** Expression : 1 + " | ||
+ | |||
+ | Main> :t " | ||
+ | " | ||
+ | |||
+ | Main> :t reverse | ||
+ | reverse :: [a] -> [a] | ||
+ | |||
+ | Main> :t map | ||
+ | map :: (a -> b) -> [a] -> [b] | ||
+ | |||
+ | |||
+ | Esta maquinaria **impide** que escribamos cualquier expresión que esté mal tipada. | ||
+ | |||
+ | Todas las funciones suelen ir encabezadas por su signatura, es decir, el nombre de la función junto al tipo de sus parámetros y resultado. El nombre va seguido de ''::'' | ||
+ | |||
+ | sgn :: Int -> Int | ||
+ | reverse :: [a] -> [a] | ||
+ | map :: (a -> b) -> [a] -> [b] | ||
+ | |||
+ | |||
+ | ===== Tuplas ===== | ||
+ | |||
+ | Haskell maneja n-uplas de manera directa. Las n-uplas nos permiten agrupar datos para manejarlos como una sola cosa, como veremos más adelante. | ||
+ | |||
+ | Incorporamos a '' | ||
+ | |||
+ | suma3upla :: (Int, | ||
+ | suma3upla (x,y,z) = x+y+z | ||
+ | |||
+ | sumaYResta :: Int -> Int -> (Int,Int) | ||
+ | sumaYResta x y = (x+y, x-y) | ||
+ | |||
+ | Y las probamos desde el // | ||
+ | |||
+ | Main> suma3upla (2,3,4) | ||
+ | 9 | ||
+ | Main> sumaYResta 2 3 | ||
+ | (5,-1) | ||
+ | |||
+ | Haskell también maneja listas de manera directa, pero lo veremos más adelante. | ||
+ | |||
+ | |||
+ | ===== Ejemplo: la función bisiesto ===== | ||
+ | |||
+ | A manera de ejemplo veamos el ejercicio 8.7 del apunte, donde tenemos que definir una función muy útil para cualquier aparato que maneje un calendario (relojes, celulares, PDAs, computadoras, | ||
+ | La signatura es //bisiesto: Int -> Bool//, y es un predicado que devuelve //true// si el año es bisiesto y //false// en caso contrario. | ||
+ | Recordemos cuando un año es [[http://es.wikipedia.org/ | ||
+ | |||
+ | La regla para los años bisiestos según el calendario gregoriano es: | ||
+ | Un año es bisiesto si es divisible por 4, excepto los principios de siglo (aquellos divisibles por 100), | ||
+ | que para ser bisiestos, también deben ser divisibles por 400. | ||
+ | |||
+ | Una definición matemática concisa sería //bisiesto n = 4|n /\ (100|n => 400|n)//. | ||
+ | |||
+ | Entonces podemos seguir agregando definiciones de funciones a nuestro archivo '' | ||
+ | Veamos tres versiones distintas ((Esto | ||
+ | |||
+ | **La del viejo programadora/ | ||
+ | |||
+ | bisiesto'' | ||
+ | bisiesto'' | ||
+ | else if n `mod` 100 /= 0 then True | ||
+ | else if n `mod` 400 == 0 then True | ||
+ | else False | ||
+ | |||
+ | **El que está aprendiendo Haskell** | ||
+ | |||
+ | bisiesto' | ||
+ | bisiesto' | ||
+ | | n `mod` 4 == 0 = n `mod` 100 /= 0 || n `mod` 400 == 0 | ||
+ | |||
+ | **El que cursó [[http:// | ||
+ | |||
+ | bisiesto :: Int -> Bool | ||
+ | bisiesto n = n `mod` 4 == 0 && (n `mod` 100 /= 0 || n `mod` 400 == 0) | ||
+ | |||
+ | Podemos poner las tres versiones en nuestro script y probarlas rápidamente usando la función '' | ||
+ | |||
+ | Main> filter bisiesto [1945..2006] | ||
+ | [1948, | ||
+ | Main> filter bisiesto' | ||
+ | [1948,1952, | ||
+ | Main> filter bisiesto'' | ||
+ | [1948, | ||
+ | |||
+ | Vemos que las tres funciones operan correctamente en el rango de números dados ((No queremos decir que sean correctas en su totalidad, solo decimos que en ese rango no tienen fallas)). | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Ejercicios ===== | ||
+ | |||
+ | Para realizar en lo que resta de la clase. | ||
+ | |||
+ | * Definir la función //sumaRat (a,b) (c,d)//, //sumaRat : (Int,Int) -> (Int,Int) -> (Int,Int)// que suma dos números racionales. En esta función vamos a usar las tuplas para agrupar datos. En este caso, vamos a representar un número racional mediante una tupla, de forma que el numerador sea el primer elemento de la tupla, y el denominador sea el segundo. Por ejemplo, representamos '' | ||
+ | |||
+ | No es necesario realizar ninguna simplificación al resultado. | ||
+ | |||
+ | probar con (1,2) y (1,2), (1,4) y (1,4). | ||
+ | |||
+ | |||
+ | * Definir una función //ordena.(x,y)//, // | ||
+ | |||
+ | probar con (0,1), (2,2), (3,1). | ||
+ | |||
+ | * Definir una función // | ||
+ | |||
+ | probar con 5 y 9, con -8 y 9, con -10 y -1, con 0 y 0 y con 0 y 3 | ||
+ | |||
+ | * Ejercicio 8.7 del Apunte\\ | ||
+ | Definir la función //edad : (Int, Int, Int) -> (Int, Int, Int) -> Int// que dadas dos fechas indica los años transcurridos entre ellas. Por ejemplo edad.(20, | ||
+ | Suponer que las fechas están siempre bien formadas y que la primera es menor o igual a la segunda. | ||
+ | |||
+ | probar con (16,4,1980) y (17, | ||
+ | |||
+ | |||
+ | * Ejercicio 8.8 del Apunte.\\ | ||
+ | En un prisma rectangular, | ||
+ | la siguiente definición del área del prisma: \\ | ||
+ | //area.h.b.d = 2 ∗ frente + 2 ∗ lado + 2 ∗ arriba// \\ | ||
+ | //|[ | ||
+ | donde //frente//, //lado// y //arriba// son las caras frontal, lateral y superior del prisma respectivamente.\\ | ||
+ | |||
+ | Completar la función // | ||
+ | |||
+ | area :: Int -> Int -> Int -> Int | ||
+ | area.h.b.d = 2*frente + 2*lado + 2*tapa | ||
+ | | ||
+ | frente = ... | ||
+ | lado = ... | ||
+ | tapa = ... |
introalg/taller08_1.1205874704.txt.gz · Última modificación: 2018/08/10 03:03 (editor externo)