introalg:taller09_3
Diferencias
Muestra las diferencias entre dos versiones de la página.
Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
introalg:taller09_3 [2009/04/11 12:52] – laura | introalg:taller09_3 [2018/08/10 03:03] (actual) – editor externo 127.0.0.1 | ||
---|---|---|---|
Línea 8: | Línea 8: | ||
A Hugs se lo invoca desde la //línea de comandos// o cliqueando sobre el icono en nuestro entorno gráfico. | A Hugs se lo invoca desde la //línea de comandos// o cliqueando 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 | + | Una vez que el intérprete está activo, la pantalla se presenta con un //prompt// a la espera de // |
+ | < | ||
[laura@azul Taller]$ hugs | [laura@azul Taller]$ hugs | ||
__ __ __ __ ____ | __ __ __ __ ____ | ||
Línea 22: | Línea 22: | ||
Type :? for help | Type :? for help | ||
Hugs.Base> | Hugs.Base> | ||
+ | </ | ||
- | De este modo Hugs se convierte en una calculadora, | + | A diferencia de prolog, el intérprete de haskell tiene muchas funciones ya definidas, las que se incluyen en el llamado [[http:// |
- | + | ||
- | A diferencia de prolog, el intérprete de haskell tiene muchas funciones ya definidas, las que se incluyen en el llamado [[http:// | + | |
+ | < | ||
Hugs.Base> | Hugs.Base> | ||
42 | 42 | ||
Línea 37: | Línea 37: | ||
Hugs.Base> | Hugs.Base> | ||
"daba le arroz al a zorra elabad" | "daba le arroz al a zorra elabad" | ||
+ | </ | ||
Podemos salir del intérprete Hugs con '' | Podemos salir del intérprete Hugs con '' | ||
+ | < | ||
Hugs.Base> | Hugs.Base> | ||
[Leaving Hugs] | [Leaving Hugs] | ||
[laura@azul Taller]$ | [laura@azul Taller]$ | ||
- | + | </ | |
- | Así volvemos al modo normal de la computadora. | + | |
=====Incorporando conocimiento===== | =====Incorporando conocimiento===== | ||
- | Para poder dar nuevas definiciones y/o funciones, además de las que se encuentran en el [[http:// | + | Para poder dar nuevas definiciones y/o funciones, además de las que se encuentran en el [[http:// |
- | + | ||
- | Como ejemplo, vamos a ver todo el proceso de **creación del programa - carga en memoria - prueba - modificación del programa - recarga**, con el Ejercicio 8.3 del apunte [[http:// | + | |
- | + | ||
- | 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. | + | |
+ | Como ejemplo, vamos a ver todo el proceso de **creación del programa - carga en memoria - prueba - modificación del programa - recarga**, con el Ejercicio 8.3 del apunte [[http:// | ||
+ | < | ||
+ | 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 programa se puede hacer mediante un editor de texto cualquiera (kate, bloc de notas, emacs...) o, si no, se puede invocar el comando para editar un (nuevo) archivo '': | Para crear un programa se puede hacer mediante un editor de texto cualquiera (kate, bloc de notas, emacs...) o, si no, se puede invocar el comando para editar un (nuevo) archivo '': | ||
- | + | < | |
- | Hugs.Base> | + | Hugs.Base> |
- | + | </ | |
- | Una posible | + | Se nos ocurre la siguiente |
- | + | < | |
- | sgn :: Int -> Int | + | sgn :: Int -> Int |
- | sgn x | 0< | + | sgn x | 0< |
- | | x< | + | | x< |
- | | x=0 = 0 | + | | x=0 = 0 |
+ | </ | ||
Escribimos esta función en el archivo, lo guardamos, y lo cargamos en la memoria del intérprete para que esté disponible para usarla. Para cargar el archivo, usamos la instrucción '': | Escribimos esta función en el archivo, lo guardamos, y lo cargamos en la memoria del intérprete para que esté disponible para usarla. Para cargar el archivo, usamos la instrucción '': | ||
+ | < | ||
+ | Hugs.Base> | ||
+ | ERROR " | ||
+ | </ | ||
+ | Pero el intérprete indica un error! Por qué? En la última línea del programa, vemos que usamos el mismo símbolo " | ||
- | Hugs.Base> | + | 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/ |
- | ERROR "cap8.hs":4 - Syntax error in input (unexpected `=') | + | |
- | Pero el intérprete | + | Para solucionar el error, corregimos '' |
+ | < | ||
+ | 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 | ||
+ | < | ||
+ | Hugs.Base> | ||
+ | Main> | ||
+ | </ | ||
+ | Ahora sí, la función | ||
- | 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 " | + | Podemos probar la nueva función con //casos de test//, y vamos a fijarnos en qué casos nos dá errores y por qué: |
+ | < | ||
+ | Main> sgn 1 | ||
+ | 1 | ||
+ | Main> sgn 0 | ||
+ | 0 | ||
+ | </code> | ||
+ | Ningún problema: funciona para los casos del manual :). | ||
+ | < | ||
+ | Main> sgn 123123123123 | ||
- | Para solucionar el error, | + | Program |
+ | |||
+ | Main> sgn 123123123 | ||
+ | 1 | ||
+ | </ | ||
+ | El número es demasiado grande y el intérprete se queda sin capacidad para tratarlo, si le damos un número más chico, sí funciona. | ||
+ | < | ||
+ | Main> sgn (-1 | ||
+ | ERROR - Syntax error in expression (unexpected end of input) | ||
+ | </ | ||
+ | Error de sintaxis: no cerramos | ||
+ | < | ||
+ | Main> sgn " | ||
+ | ERROR - Type error in application | ||
+ | *** Expression | ||
+ | *** Term : " | ||
+ | *** Type : String | ||
+ | *** Does not match : Int | ||
+ | </ | ||
+ | Error de tipos: la función está definida para trabajar con enteros | ||
+ | < | ||
+ | Main> sgn 1.1 | ||
+ | ERROR - Cannot infer instance | ||
+ | *** Instance | ||
+ | *** Expression : sgn 1.1 | ||
+ | </ | ||
+ | Error de tipos: la función está definida para trabajar con enteros (Int), | ||
+ | < | ||
+ | Main> sgn -1 | ||
+ | ERROR - Cannot infer instance | ||
+ | *** Instance | ||
+ | *** Expression : sgn - 1 | ||
- | | + | Main> |
- | sgn x | 0< | + | -1 |
- | | x<0 | + | </code> |
- | | x==0 = 0 | + | Error de precedencia: |
- | Luego de guardar | + | =====Cómo declaramos |
- | Hugs.Base> :l cap8.hs | + | La declaración del conocimiento en haskell tiene algunos parecidos y algunas diferencias con la declaración del conocimiento en prolog. |
- | Main> | + | |
- | Ahora sí, la función es correcta | + | Vemos que haskell declara el conocimiento en forma de // |
+ | < | ||
+ | sgn :: Int -> Int | ||
+ | sgn x | 0< | ||
+ | | x< | ||
+ | | x==0 = 0 | ||
+ | </ | ||
+ | La primera línea es la //signatura de tipos//, de la que vamos a hablar en la siguiente sección. Las otras tres líneas son la definición de la función. Podemos ver que esta función | ||
- | Podemos probar | + | Por lo tanto, lo que hay a la izquierda del símbolo " |
+ | < | ||
+ | sgn(X,Y) :- (0<X , Y=1) ; (X<0 , Y=(-1)) ; (X=0, Y=0). | ||
+ | </code> | ||
+ | y la consultaríamos de la siguiente manera: | ||
+ | < | ||
+ | ?- sgn(33, | ||
+ | Y = 1 . | ||
+ | </ | ||
+ | De esta forma, indicamos que la variable " | ||
- | Main> sgn 1 | + | Al igual que en prolog, las variables que se usan en haskell tienen alcance únicamente dentro de la definición de la función, pero, a diferencia de prolog, las variables se escriben en minúscula, de la misma forma que el nombre de las funciones. |
- | 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 " | + | |
- | ERROR - Type error in application | + | |
- | *** Expression | + | |
- | *** Term : " | + | |
- | *** Type : String | + | |
- | *** Does not match : Int | + | |
- | + | ||
- | Main> map sgn [-10..10] | + | |
- | [-1,-1,-1,-1,-1,-1, | + | |
+ | Vemos que al definir '' | ||
- | Notamos los distintos tipos de errores | + | Vamos a ver que en haskell hay varias formas |
- | * Precedencia ('' | + | |
- | * Tipos ('' | + | |
- | * Sintaxis ('' | + | |
- | ===== Inferencia | + | ===== Tipos de datos===== |
- | Haskell es un lenguaje tipado, es decir, | + | Haskell es un lenguaje tipado, es decir, |
< | < | ||
- | | + | sgn :: Int -> Int -- esta línea es la signatura de tipos de la función sgn |
- | sgn x | 0< | + | sgn x | 0< |
- | | x< | + | | x< |
- | | x==0 = 0 | + | | x==0 = 0 |
</ | </ | ||
La signatura de tipos está formada por el nombre de la función y el tipo de sus parámetros y resultado. El nombre va seguido de ''::'' | La signatura de tipos está formada por el nombre de la función y el tipo de sus parámetros y resultado. El nombre va seguido de ''::'' | ||
< | < | ||
- | | + | sgn :: Int -> Int |
- | reverse :: [a] -> [a] | + | reverse :: [a] -> [a] |
- | map :: (a -> b) -> [a] -> [b] | + | map :: (a -> b) -> [a] -> [b] |
</ | </ | ||
Pequeño ejercicio sobre la aridad((Recuerden que la aridad es el número de argumentos de la función: unaria si tiene un argumento, binaria si tiene dos, etc.)) de las funciones: cuál de estas tres funciones es unaria, cuál binaria, cuál ternaria? | Pequeño ejercicio sobre la aridad((Recuerden que la aridad es el número de argumentos de la función: unaria si tiene un argumento, binaria si tiene dos, etc.)) de las funciones: cuál de estas tres funciones es unaria, cuál binaria, cuál ternaria? | ||
Línea 186: | Línea 221: | ||
De esta forma, nos resulta imposible escribir cualquier expresión que esté mal tipada, es decir, usando tipos distintos a los que se declaran en la definición de la función. De hecho, corre el rumor de que, en una versión de desarrollo de un popular intérprete de haskell (GHC), si el intérprete encontraba un error de tipos, borraba todo el código fuente! :-} | De esta forma, nos resulta imposible escribir cualquier expresión que esté mal tipada, es decir, usando tipos distintos a los que se declaran en la definición de la función. De hecho, corre el rumor de que, en una versión de desarrollo de un popular intérprete de haskell (GHC), si el intérprete encontraba un error de tipos, borraba todo el código fuente! :-} | ||
+ | Los tipos de datos se declaran con la primera letra en mayúscula: Int, Float, Char, String, etc. En cambio, las variables se declaran en minúscula. | ||
+ | |||
+ | Veamos algunos de los tipos de datos que maneja haskell: diferentes tipos de números, letras, tuplas y listas. | ||
+ | |||
+ | ====Letras y números==== | ||
+ | |||
+ | En haskell tenemos diferentes tipos de números. Los que más vamos a estar usando son los enteros, que se llaman '' | ||
+ | |||
+ | También tenemos el tipo '' | ||
- | =====Algunos tipos de datos===== | ||
====Tuplas==== | ====Tuplas==== | ||
- | Las n-uplas son conjuntos con un número y orden de elementos predefinido. Los más conocidos son las tuplas, conjuntos de dos elementos, pero también hay triplas, cuatruplas, etc. La utilidad de las n-uplas es que nos permiten agrupar datos para manejarlos como una sola cosa. | + | Las n-uplas son conjuntos con un número y orden de elementos predefinido. Se escriben entre paréntesis y se separan los elementos mediante comas. Los más conocidos son las tuplas, conjuntos de dos elementos, pero también hay triplas, cuatruplas, etc. La utilidad de las n-uplas es que nos permiten agrupar datos para manejarlos como una sola cosa. |
Veamos algunos ejemplos: | Veamos algunos ejemplos: | ||
< | < | ||
- | | + | suma3upla :: (Int, |
- | suma3upla (x,y,z) = x+y+z | + | suma3upla (x,y,z) = x+y+z |
- | + | </ | |
- | sumaYResta :: Int -> Int -> (Int,Int) | + | < |
- | sumaYResta x y = (x+y, x-y) | + | sumaYResta :: Int -> Int -> (Int,Int) |
+ | sumaYResta x y = (x+y, x-y) | ||
</ | </ | ||
Línea 210: | Línea 254: | ||
(5,-1) | (5,-1) | ||
</ | </ | ||
+ | |||
+ | Las tuplas pueden contener cualquier elemento de cualquier tipo, y se pueden mezclar tipos dentro de una misma tupla. Por ejemplo, podemos tener que el primer elemento de una tupla sea una cadena de caracteres y el segundo un número, el primero, una lista, el segundo elemento un booleano y el tercero otra lista, y así todas las combinaciones que se les ocurran. | ||
====Listas==== | ====Listas==== | ||
- | Con las listas | + | Las listas |
+ | |||
+ | Las listas se escriben entre corchetes y se separan los elementos mediante comas. Pero esta forma de representar las listas es una forma abreviada de escribir lo que haskell interpreta internamente como una anidación de tuplas de profundidad indeterminada. De hecho '' | ||
+ | Dado que las listas son en realidad anidaciones de tuplas, podemos trabajar con su estructura como tuplas, y separar la parte inicial de la lista del resto, lo que se suele llamar //cabeza// y //cola//. Por ejemplo, en la siguiente función: | ||
< | < | ||
esVacia :: [a] -> Bool | esVacia :: [a] -> Bool | ||
Línea 221: | Línea 270: | ||
</ | </ | ||
- | Por cierto | + | Pero no sólo podemos distinguir el primer elemento de una lista, podemos distinguir //cualquier fracción inicial//. Cuando decimos |
+ | < | ||
+ | tercero [a] -> a | ||
+ | tercero [_:_:x:_] = x | ||
+ | </ | ||
+ | |||
+ | Sin embargo, podemos dejar el resto de la lista sin detallar cuántos elementos hay. No podemos distinguir fracciones finales de las listas porque la estructura de tuplas requiere que para distinguir el //n+1// elemento de una tupla hayamos distinguido el elemento //n//. | ||
+ | Definimos un predicado que decide si //hay 2 o más elementos en una lista//: | ||
+ | < | ||
+ | alMenos2 :: [a] -> Bool | ||
+ | alMenos2 [] = False | ||
+ | alMenos2 [x] = False | ||
+ | alMenos2 (x:y:xs) = True | ||
+ | </ | ||
+ | |||
+ | =====Comparación de patrones===== | ||
+ | |||
+ | En haskell, como en prolog, las diferentes funciones se aplican por **unificación**. Es decir, cuando el intérprete trata de resolver algo, lo resuelve buscando alguna definición de función cuya parte izquierda pueda unificarse con lo que el intérprete está tratando de resolver. | ||
+ | |||
+ | Cómo hace el intérprete para llegar desde nuestra pregunta al resultado? En el siguiente ejemplo: | ||
+ | < | ||
+ | Main> alMenos2 [1,2,3,4,5] | ||
+ | True | ||
+ | </ | ||
+ | El intérprete busca alguna definición de función que pueda unificar con '' | ||
+ | < | ||
+ | alMenos2 [] = False | ||
+ | </ | ||
+ | Pero este caso no le sirve porque no puede unificar la lista vacía '' | ||
+ | |||
+ | Después encuentra otro caso en el que se define '' | ||
+ | < | ||
+ | alMenos2 [x] = False | ||
+ | </ | ||
+ | Finalmente, encuentra un caso de una lista con dos o más elementos, con la que sí puede unificar: | ||
+ | < | ||
+ | alMenos2 (x:y:xs) = True | ||
+ | </ | ||
+ | Vamos a prestar un poco más de atención al patrón que describe listas con uno o más elementos. En primer lugar vemos que se usan paréntesis. No es porque se trate de una tupla, sino para evitar errores de precedencia con el operador "'':''" | ||
+ | < | ||
+ | alMenos2 | ||
+ | ----------- | ||
+ | [a] -> Bool | ||
+ | | ||
+ | : [a] | ||
+ | | ||
+ | [a] | ||
+ | -------------------------- | ||
+ | Bool | ||
+ | </ | ||
+ | Notemos que hemos usado la variable '' | ||
+ | |||
+ | A la unificación también se la llama correspondencia de patrones o //pattern matching//, y a los elementos que unifican se los puede llamar patrones. Así, los diferentes casos que especificamos al definir por casos una función se pueden llamar también " | ||
+ | |||
+ | ====El patrón irrefutable==== | ||
+ | |||
+ | Hemos visto que las variables se escriben con minúscula. Como en prolog, también tenemos una variable comodín, que puede unificar con cualquier cosa, y se escribe de la misma forma que en prolog, con el guión bajo " | ||
+ | |||
+ | Veamos algunos ejemplos de uso del patrón irrefutable. Recuerden que habíamos visto la función '' | ||
+ | < | ||
+ | esVacia :: [a] -> Bool | ||
+ | esVacia [] = True | ||
+ | esVacia (x:xs) = False | ||
+ | </ | ||
+ | Podemos usar comodines en ambas partes del segundo patrón o bien un patrón irrefutable y comodín a la vez. | ||
< | < | ||
esVacia' | esVacia' | ||
Línea 233: | Línea 346: | ||
</ | </ | ||
- | Veamos que tenemos más posibilidades que cabeza y cola. | + | También se puede aplicar a la función '' |
- | Definimos un predicado que decide si //hay 2 o más elementos en una lista// y damos dos versiones una bastante legible y la otra ultracompacta y un tanto más críptica | + | |
< | < | ||
alMenos2 :: [a] -> Bool | alMenos2 :: [a] -> Bool | ||
Línea 241: | Línea 352: | ||
alMenos2 [x] = False | alMenos2 [x] = False | ||
alMenos2 (x:y:xs) = True | alMenos2 (x:y:xs) = True | ||
+ | </ | ||
+ | Esta segunda versión es bastante más difícil de leer que la primera, por el uso y abuso del orden de evaluación de los patrones, patrones irrefutables y comodines. Los patrones irrefutables son muy útiles, pero no debemos dejar que nos impidan entender lo que escribimos ;). | ||
+ | < | ||
alMenos2' | alMenos2' | ||
alMenos2' | alMenos2' | ||
Línea 247: | Línea 360: | ||
</ | </ | ||
- | La probamos para ver si funciona de manera correcta y notamos el uso de **listas de listas** para que //map// haga operar a la función // | + | Veamos ahora un ejemplo |
- | + | ||
- | Main> map alMenos2 [ [], [1..1], [1..2], [1..3], [1..4], [1..10000] ] | + | |
- | [False, | + | |
- | Main> map alMenos2' | + | |
- | [False, | + | |
- | + | ||
- | + | ||
- | =====Comparación de patrones===== | + | |
- | + | ||
- | Los patrones numéricos consisten en constantes y expresiones numéricas simples. | + | |
< | < | ||
Línea 267: | Línea 370: | ||
Si probamos | Si probamos | ||
+ | < | ||
+ | Main> esCeroOUno 1 | ||
+ | False | ||
+ | </ | ||
- | Main> esCeroOUno 1 | + | Por qué nos devuelve falso? Porque en haskell, como en prolog, los patrones se aplican en el **orden** en el que se encuentran en el archivo de la base de conocimiento: |
- | False | + | |
- | El problema surge del hecho que los patrones | + | El programa |
- | En éste caso el segundo | + | |
- | El programa correcto sería: | + | |
< | < | ||
Línea 282: | Línea 386: | ||
</ | </ | ||
- | Podemos combinar de manera libre estas posibilidades como se muestra a continuación. | ||
- | < | + | ===== Un ejemplo: la función bisiesto ===== |
- | sumaCabeza :: [(Int,Int)] -> Int | + | |
- | sumaCabeza [] = 0 | + | |
- | sumaCabeza ((x, | + | |
- | </ | + | |
- | + | ||
- | < | + | |
- | ordenaCabeza :: [(Int,Int)] -> (Int,Int) | + | |
- | ordenaCabeza [] = error "No hay cabeza" | + | |
- | ordenaCabeza (h@(x, | + | |
- | where | + | |
- | ordena (x,y) | x<=y = (x,y) | + | |
- | | otherwise = (y,x) | + | |
- | </ | + | |
- | + | ||
- | Probamos estos códigos | + | |
- | + | ||
- | Main> sumaCabeza [(1, | + | |
- | 6 | + | |
- | Main> ordenaCabeza [(10, | + | |
- | (10,20) | + | |
- | Main> ordenaCabeza [(20, | + | |
- | (10,20) | + | |
- | Main> ordenaCabeza [] | + | |
- | + | ||
- | Program error: No hay cabeza | + | |
- | + | ||
- | Main> ordenaCabeza (take 10 (repeat (2,1))) | + | |
- | (1,2) | + | |
- | + | ||
- | ===== 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, | 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, | ||
Línea 326: | Línea 399: | ||
Una definición matemática concisa sería //bisiesto n = 4|n /\ (100|n => 400|n)//. | 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 es una mala copia de [[http:// | Veamos tres versiones distintas ((Esto es una mala copia de [[http:// | ||
- | **La del viejo programadora/ | + | **La del programadora/ |
bisiesto'' | bisiesto'' | ||
Línea 343: | Línea 415: | ||
| n `mod` 4 == 0 = n `mod` 100 /= 0 || n `mod` 400 == 0 | | n `mod` 4 == 0 = n `mod` 100 /= 0 || n `mod` 400 == 0 | ||
- | **El que cursó [[http:// | + | **El que entiende mucho de programación declarativa |
bisiesto :: Int -> Bool | bisiesto :: Int -> Bool | ||
bisiesto n = n `mod` 4 == 0 && (n `mod` 100 /= 0 || n `mod` 400 == 0) | bisiesto n = n `mod` 4 == 0 && (n `mod` 100 /= 0 || n `mod` 400 == 0) | ||
- | |||
- | =====Comparando haskell y prolog===== | ||
- | |||
- | Ejemplo de la familia. | ||
===== Ejercicios ===== | ===== Ejercicios ===== | ||
+ | Hay muchos ejercicios para hacer, no se preocupen si no pueden terminarlos todos!! Vamos a ver algunos de ellos en la próxima clase para consolidar los conceptos que hemos visto en esta. | ||
- | + | | |
- | * 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). | + | |
- | + | ||
- | + | ||
- | | + | |
probar con (0,1), (2,2), (3,1). | probar con (0,1), (2,2), (3,1). | ||
- | * Definir una función // | + | * 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 | 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\\ | * 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, | + | Definir la función // |
Suponer que las fechas están siempre bien formadas y que la primera es menor o igual a la segunda. | Suponer que las fechas están siempre bien formadas y que la primera es menor o igual a la segunda. | ||
Línea 382: | Línea 443: | ||
En un prisma rectangular, | En un prisma rectangular, | ||
la siguiente definición del área del prisma: \\ | la siguiente definición del área del prisma: \\ | ||
- | //area.h.b.d = 2 ∗ frente + 2 ∗ lado + 2 ∗ arriba// \\ | + | //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.\\ | donde //frente//, //lado// y //arriba// son las caras frontal, lateral y superior del prisma respectivamente.\\ | ||
- | Completar la función //area.h.b.d// //area : Int -> Int -> Int -> Int// que calcula el área de un prisma rectangular: | + | Completar la función //area h b d// // |
area :: Int -> Int -> Int -> Int | area :: Int -> Int -> Int -> Int | ||
- | area.h.b.d = 2*frente + 2*lado + 2*tapa | + | area h b d = 2*frente + 2*lado + 2*tapa |
where | where | ||
frente = ... | frente = ... | ||
lado = ... | lado = ... | ||
tapa = ... | tapa = ... | ||
+ | |||
+ | * Programar en haskell una [[http:// | ||
+ | |||
+ | * Definir la función //cabeza xs//, //cabeza :: [a] --> a//, que devuelve el primer elemento de una lista. | ||
+ | |||
+ | probar con [1,2,3], con [3,3,3] y con []. | ||
+ | |||
+ | * Definir la función //cola xs//, //cola :: [a] --> [a]//, que devuelve toda la lista menos el primer elemento. | ||
+ | |||
+ | probar con [1,2,3], con [3,3,3] y con []. | ||
+ | |||
+ | * Definir una función // | ||
+ | |||
+ | probar con [1,2,3], con [3,3,3], con [0], con [0,1] y con []. | ||
+ | |||
+ | * Definir una función // | ||
+ | |||
+ | probar con (1,2) y [3,2,4,5], (0,0) y [], (1,2) y [2,3,4,5]. | ||
+ | |||
+ | * Definir una función // | ||
+ | Ayuda: fíjense que el resultado siempre debe ser una lista de caracteres! | ||
+ | |||
+ | probar con [' | ||
+ | |||
+ | * Definir una función // |
introalg/taller09_3.1239454330.txt.gz · Última modificación: 2018/08/10 03:03 (editor externo)