Herramientas de usuario

Herramientas del sitio


introalg:taller09_3

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:taller09_3 [2009/04/13 12:35] lauraintroalg:taller09_3 [2018/08/10 03:03] (actual) – editor externo 127.0.0.1
Línea 24: Línea 24:
 </code> </code>
  
-A diferencia de prolog, el intérprete de haskell tiene muchas funciones ya definidas, las que se incluyen en el llamado [[http://www.haskell.org/onlinereport/standard-prelude.html | preludio estándar]]. Entre ellas están todas las aritméticas y las lógicas básicas, pero también otras muchas, como por ejemplo "reverse":+A diferencia de prolog, el intérprete de haskell tiene muchas funciones ya definidas, las que se incluyen en el llamado [[http://www.haskell.org/onlinereport/standard-prelude.html | preludio estándar]]. Entre ellas están todas las aritméticas y las lógicas básicas, pero también otras muchas, como por ejemplo "reverse". Veamos algunos ejemplos de cómo funcionan:
  
 <code> <code>
Línea 44: Línea 44:
   [laura@azul Taller]$   [laura@azul Taller]$
 </code> </code>
-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://www.haskell.org/onlinereport/standard-prelude.html | preludio estándar]], necesitamos escribir un programa de Haskell. Lo haremos con un archivo terminado en ''.hs'', donde escribiremos en texto plano todas las definiciones que conforman el programa+Para poder dar nuevas definiciones y/o funciones, además de las que se encuentran en el [[http://www.haskell.org/onlinereport/standard-prelude.html | preludio estándar]], necesitamos escribir un programa de haskell. Lo haremos con un archivo terminado en ''.hs'', donde escribiremos en texto plano todas las definiciones que conforman el programa.
- +
-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://cs.famaf.unc.edu.ar/introalg/calculo_extracto.pdf|Extracto del Cálculo de Programas]]: +
- +
-  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://cs.famaf.unc.edu.ar/introalg/calculo_extracto.pdf|Extracto del Cálculo de Programas]], que tiene el siguiente enunciado:
 +<code>
 +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.
 +</code>
 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 '':e cap8.hs'' desde el intérprete mismo:  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 '':e cap8.hs'' desde el intérprete mismo: 
 <code> <code>
-  Hugs.Base> :e cap8.hs+Hugs.Base> :e cap8.hs
 </code> </code>
-Una posible solución para el problema de la función signo es la siguiente:+Se nos ocurre la siguiente solución para el problema de la función ''sgn'':
 <code> <code>
 sgn :: Int -> Int sgn :: Int -> Int
Línea 72: Línea 71:
 ERROR "cap8.hs":4 - Syntax error in input (unexpected `=') ERROR "cap8.hs":4 - Syntax error in input (unexpected `=')
 </code> </code>
-Pero el intérprete indica un error! Por qué? En la última línea del programa, vemos que usamos el mismo símbolo "=" para dos cosas: para definir (parecido a como usábamos ":-" en prolog) y para comparar, pero en realidad el símbolo "=" sólo se puede usar para definir. Para comparar tenemos que usar el símbolo "==".+Pero el intérprete indica un error! Por qué? En la última línea del programa, vemos que usamos el mismo símbolo "=" para dos cosas muy distintas: para separar una condición de la forma como se calcula el resultado si la condición es cierta y para comparar dos valores. Pero en realidad el símbolo "=" sólo se puede usar para definir. Para comparar tenemos que usar el símbolo "==".
  
 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" a Haskell]]. 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" a Haskell]].
Línea 106: Línea 105:
 1 1
 </code> </code>
-El número es demasiado grande y el intérprete se queda sin capacidad para tratarlo.+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.
 <code> <code>
 Main> sgn (-1 Main> sgn (-1
Línea 150: Línea 149:
         | x==0   = 0         | x==0   = 0
 </code> </code>
-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 está definida por análisis por casos, distinguiendo tres casos: cuando x es positivo (''0<x''), cuando x es negativo (''x<0'') o cuando x es 0 (''x==0''). Estos tres casos se relacionan entre ellos mediante el símbolo "|", que indica disyunción. +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 está definida por análisis por casos, distinguiendo tres casos: cuando x es positivo (''0<x''), cuando x es negativo (''x<0'') o cuando x es 0 (''x==0''). Estos tres casos se relacionan entre ellos mediante el símbolo "|", que indica disyunción. El intérprete va a ir evaluando cada uno de los casos en el orden en el que los encuentra en el archivo del programa, y cuando encuentre uno con el que pueda unificar lo que quiere resolver, lo va a aplicar y va a terminar.
  
 Por lo tanto, lo que hay a la izquierda del símbolo "|" tiene una función parecida a la de la cabeza de una regla de prolog, lo que hay a la derecha sería parecido al cuerpo de una regla, con algunas diferencias. Noten que la cabeza de una regla prolog tiene toda la información sobre el nombre de la función y sus argumentos, al igual que la parte izquierda de una definición de función en haskell. Sin embargo, en haskell hay un elemento implícito, el resultado, que en prolog debe estar explícito. Si escribiéramos la función ''sgn'' en prolog, la escribiríamos así: Por lo tanto, lo que hay a la izquierda del símbolo "|" tiene una función parecida a la de la cabeza de una regla de prolog, lo que hay a la derecha sería parecido al cuerpo de una regla, con algunas diferencias. Noten que la cabeza de una regla prolog tiene toda la información sobre el nombre de la función y sus argumentos, al igual que la parte izquierda de una definición de función en haskell. Sin embargo, en haskell hay un elemento implícito, el resultado, que en prolog debe estar explícito. Si escribiéramos la función ''sgn'' en prolog, la escribiríamos así:
Línea 165: Línea 164:
 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. 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.
  
-Vemos que al definir ''sgn'' en haskell hemos distinguido dos partes del cuerpo, mediante el símbolo "=". A la izquierda de "=" hemos escrito una condición y, si ésta se cumple, se calcula el resultado de la forma que se especifica a la derecha. Si no se cumple, se pasa a la siguiente disyunción. En prolog no disponemos de ese mecanismo, y por lo tanto nos hemos visto obligados a especificar esas dos partes de cada elemento de la disyunción con la misma categoría dentro de la proposición. Si derivamos la prueba de cada programa, vamos a ver que el resultado de ambos es el mismo, pero la función en haskell resulta mucho más natural y más fácil de leer.+Vemos que al definir ''sgn'' en haskell hemos distinguido dos partes del cuerpo, mediante el símbolo "=". A la izquierda de "=" hemos escrito una condición y, si ésta se cumple, se calcula el resultado de la forma que se especifica a la derecha. Si no se cumple, se pasa al siguiente elemento de la disyunción. En prolog no disponemos de ese mecanismo, y por lo tanto nos hemos visto obligados a especificar esas dos partes de cada elemento de la disyunción con la misma categoría dentro de la proposición. Si derivamos la prueba de cada programa, vamos a ver que el resultado de ambos es el mismo, pero la función en haskell resulta mucho más natural y más fácil de leer.
  
 Vamos a ver que en haskell hay varias formas de expresar estas condiciones para que se cumpla una determinada forma de calcular un resultado, en el apartado sobre [[#comparacion_de_patrones|comparación de patrones]]. Ahora vamos a ver un poco más sobre tipos de datos en haskell. Vamos a ver que en haskell hay varias formas de expresar estas condiciones para que se cumpla una determinada forma de calcular un resultado, en el apartado sobre [[#comparacion_de_patrones|comparación de patrones]]. Ahora vamos a ver un poco más sobre tipos de datos en haskell.
Línea 172: Línea 171:
 ===== Tipos de datos===== ===== Tipos de datos=====
  
-Haskell es un lenguaje tipado, es decir, todos dato pertenece a una clase o tipo de datos. En general, la definición de una función va precedida de su //signatura de tipos//, donde declaramos los tipos que están involucrados en la función:+Haskell es un lenguaje tipado, es decir, todo dato pertenece a una clase o tipo de datos. En general, la definición de una función va precedida de su //signatura de tipos//, donde declaramos los tipos que están involucrados en la función:
 <code> <code>
-  sgn :: Int -> Int     -- esta línea es la signatura de tipos de la función sgn +sgn :: Int -> Int     -- esta línea es la signatura de tipos de la función sgn 
-  sgn x   | 0<  = 1 +sgn x   | 0<  = 1 
-          | x<  = -1 +        | x<  = -1 
-          | x==0  = 0+        | x==0  = 0
 </code> </code>
  
 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 ''::'' y los parámetros y el resultado van separados por ''->''. Por ejemplo: 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 ''::'' y los parámetros y el resultado van separados por ''->''. Por ejemplo:
 <code> <code>
-  sgn :: Int -> Int +sgn :: Int -> Int 
-  reverse :: [a] -> [a] +reverse :: [a] -> [a] 
-  map :: (a -> b) -> [a] -> [b]+map :: (a -> b) -> [a] -> [b]
 </code> </code>
 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 239: Línea 238:
 Veamos algunos ejemplos: Veamos algunos ejemplos:
 <code> <code>
-  suma3upla :: (Int,Int,Int) -> Int +suma3upla :: (Int,Int,Int) -> Int 
-  suma3upla (x,y,z) = x+y+z +suma3upla (x,y,z) = x+y+z 
-   +</code> 
-  sumaYResta :: Int -> Int -> (Int,Int) +<code>   
-  sumaYResta x y = (x+y, x-y)+sumaYResta :: Int -> Int -> (Int,Int) 
 +sumaYResta x y = (x+y, x-y)
 </code> </code>
  
Línea 269: Línea 269:
 esVacia (x:xs) = False esVacia (x:xs) = False
 </code> </code>
-Por cierto que podemos usar comodines en ambas partes del segundo patrón o bien un patrón irrefutable y comodín a la vez. 
-<code> 
-esVacia' :: [a] -> Bool 
-esVacia' []    = True 
-esVacia' (_:_) = False 
  
-esVacia'' :: [a] -> Bool +Pero no sólo podemos distinguir el primer elemento de una lista, podemos distinguir //cualquier fracción inicial//. Cuando decimos que podemos distinguir cualquier fracción inicial de una lista, lo que queremos decir es que nos podemos referir al n-ésimo elemento de una lista, eso sí, para hacerlo tenemos que hacerlo con un patrón en el que se representen todos los elementos desde el primero hasta el n-1. Por ejemplo, si queremos referirnos al tercer elemento de una lista, tendremos que referirnos también al primero y al segundo, aunque sea mediante un patrón irrefutable, por ejemplo, de esta forma: 
-esVacia'' [] = True +<code> 
-esVacia''  False+tercero [a] -> a 
 +tercero [_:_:x:_] x
 </code> </code>
  
-Pero no sólo podemos distinguir el primer elemento de una lista, podemos distinguir //cualquier fracción inicial// 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//+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// y damos dos versiones una bastante legible y la otra ultracompacta y un tanto más críptica que hace uso y abuso del orden de evaluación de los patrones, patrones irrefutables y comodines.+
  
 +Definimos un predicado que decide si //hay 2 o más elementos en una lista//:
 <code> <code>
 alMenos2 :: [a] -> Bool alMenos2 :: [a] -> Bool
Línea 289: Línea 284:
 alMenos2 [x]      = False alMenos2 [x]      = False
 alMenos2 (x:y:xs) = True alMenos2 (x:y:xs) = True
- 
-alMenos2' :: [a] -> Bool 
-alMenos2' (_:_:_) = True 
-alMenos2' _       = False 
 </code> </code>
  
Línea 299: Línea 290:
 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.  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. 
  
-****ejemplos de unificación y no unificación****+Cómo hace el intérprete para llegar desde nuestra pregunta al resultado? En el siguiente ejemplo: 
 +<code> 
 +Main> alMenos2 [1,2,3,4,5] 
 +True 
 +</code> 
 +El intérprete busca alguna definición de función que pueda unificar con ''alMenos2 [1,2,3,4,5]''. En primer lugar, encuentra un primer caso en el que se define ''alMenos2'': 
 +<code> 
 +alMenos2 []       = False 
 +</code> 
 +Pero este caso no le sirve porque no puede unificar la lista vacía ''[]'' con la lista no vacía ''[1,2,3,4,5]''.
  
-Si unifica, el intérprete pasa a ver si la parte derecha de la función devuelve truesustituyendo las variables por el valor resultante de la unificación+Después encuentra otro caso en el que se define ''alMenos2'', pero tampoco puede unificar una lista de un elemento con una lista de 5. 
- +<code> 
-*** ejemplo***+alMenos2 [x]      = False 
 +</code> 
 +Finalmente, encuentra un caso de una lista con dos o más elementos, con la que sí puede unificar: 
 +<code> 
 +alMenos2 (x:y:xs) = True 
 +</code> 
 +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 tuplasino para evitar errores de precedencia con el operador "'':''". Este operador es una función binaria que toma un elemento y una lista y nos indica que ese elemento está dentro de la lista, en su cabezaSi hacemos el árbol de tipado de la expresión ''alMenos2 (x:y:xs)'', nos quedará de la siguiente forma: 
 +<code> 
 +alMenos2    ( x : y :  xs ) 
 +-----------  --- ---  ---- 
 +[a] -> Bool     a : [a] 
 +                 --------- 
 +                :   [a] 
 +             ------------- 
 +                 [a] 
 +-------------------------- 
 +       Bool 
 +</code> 
 +Notemos que hemos usado la variable ''xs'' para describir una lista con un número indeterminado de elementos. En este caso hemos usado ''xs'' que es un nombre de variable muy usado en haskell para listas, pero podríamos haber usado cualquier otra variable: ''cola'', ''resto'', ''lista'', ''a'' o lo que fuera. La variable representa una lista porque si no no podría tipar con el operador ":", que requiere que su segundo argumento sea una lista. En cualquier caso, esta lista puede ser una lista cualquiera, incluyendo la lista vacía.
  
 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 "patrones". 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 "patrones".
Línea 309: Línea 327:
 ====El patrón irrefutable==== ====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 un ejemplo de su uso:+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'': 
 +<code> 
 +esVacia :: [a] -> Bool 
 +esVacia []     = True 
 +esVacia (x:xs) = False 
 +</code> 
 +Podemos usar comodines en ambas partes del segundo patrón o bien un patrón irrefutable y comodín a la vez. 
 +<code> 
 +esVacia' :: [a] -> Bool 
 +esVacia' []    = True 
 +esVacia' (_:_) = False 
 + 
 +esVacia'' :: [a] -> Bool 
 +esVacia'' [] = True 
 +esVacia'' _  = False 
 +</code> 
 + 
 +También se puede aplicar a la función ''alMenos2'', que definíamos originalmente así: 
 +<code> 
 +alMenos2 :: [a] -> Bool 
 +alMenos2 []       = False 
 +alMenos2 [x]      = False 
 +alMenos2 (x:y:xs) = True 
 +</code> 
 +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 ;). 
 +<code> 
 +alMenos2' :: [a] -> Bool 
 +alMenos2' (_:_:_) = True 
 +alMenos2' _       = False 
 +</code> 
 + 
 +Veamos ahora un ejemplo de **mal** uso del patrón irrefutable:
  
 <code> <code>
Línea 372: Línea 423:
 ===== 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 una función //ordena.(x,y)//, //ordena : (Int,Int) -> (Int,Int)// que, dados dos enteros, los ordena de  menor a mayor.+  * Definir una función //ordena (x,y)//, //ordena :: (Int,Int) -> (Int,Int)// que, dados dos enteros, los ordena de  menor a mayor.
  
   probar con (0,1), (2,2), (3,1).   probar con (0,1), (2,2), (3,1).
  
-  * Definir una función //ambospositivos.x.y//, //ambospositivos : Int -> Int -> Bool//, que dados dos enteros devuelve //True// si los dos son positivos.+  * Definir una función //ambospositivos x y//, //ambospositivos :: Int -> Int -> Bool//, que dados dos enteros devuelve //True// si los dos son positivos.
  
   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,10,1968).(30,4,1987) = 18.+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,10,1968) (30,4,1987) = 18.
 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 391: Línea 443:
 En un prisma rectangular, llamemos //h// a la altura, //b// al ancho y //d// a la profundidad. Completar En un prisma rectangular, llamemos //h// a la altura, //b// al ancho y //d// a la profundidad. Completar
 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// \\
 //|[   ...aca va la definicion...   ]|// \\ //|[   ...aca va la definicion...   ]|// \\
 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// que calcula el área de un prisma rectangular:
  
       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 = ...
Línea 406: Línea 458:
   * Programar en haskell una [[http://www.cs.famaf.unc.edu.ar/wiki/doku.php?id=introalg:taller09_soluciones#familia|solución al problema de la familia]] que vimos en prolog.   * Programar en haskell una [[http://www.cs.famaf.unc.edu.ar/wiki/doku.php?id=introalg:taller09_soluciones#familia|solución al problema de la familia]] que vimos en prolog.
  
 +  * 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 //esVaciaOPrimer0 xs//, //esVaciaOPrimer0 :: [Int] -> Bool// que dada una lista //xs// decida si //xs// es vacía o bien su primer elemento es 0.
 +
 +  probar con [1,2,3], con [3,3,3], con [0], con [0,1] y con [].
 +
 +  * Definir una función //segundoEsSegundo (x,y) zs//, //segundoEsSegundo :: (Int,Int) -> [Int] -> Bool// que dada una tupla de enteros //(x,y)// y una lista de enteros //zs// comprueba si el segundo elemento de la tupla es igual al segundo elemento de la lista.
 +
 +  probar con (1,2) y [3,2,4,5], (0,0) y [], (1,2) y [2,3,4,5].
 +
 +  * Definir una función //recortaDia xs//, //recortaDia :: [Char] -> [Char]// que dada una lista de caracteres //xs//, comprueba si las letras de la lista forman el nombre de un día de la semana, si es así, si el día no es del fin de semana, devuelven la primera letra solamente, en cambio, si el día es de fin de semana, devuelven el nombre del día completo.
 +Ayuda: fíjense que el resultado siempre debe ser una lista de caracteres!
 +
 +  probar con ['l','u','n','e','s'], ['d','o','m','i','n','g','o'], [].
 +
 +  * Definir una función //otorgaBeca (x,y,z)//, //otorgaBeca :: (Int,Int,Int) -> String// que dada una tresupla con la edad del candidato, su promedio y su ingreso anual, devuelva una recomendación sobre su adecuación para un programa de becas, en tres rangos: "Muy Adecuado", "Adecuado" y "Poco Adecuado". Aplicando "divide y vencerás", usar procedimientos distintos para candidatos menores de 30 años y mayores de 30, para candidatos con un ingreso anual mayor que 15000, entre 15000 y 10000 y menor que 10000, y para candidatos con un promedio mayor a 8, entre 6 y 8, entre 6 y 4 y menor a 4.
introalg/taller09_3.1239626129.txt.gz · Última modificación: 2018/08/10 03:03 (editor externo)