Herramientas de usuario

Herramientas del sitio


introalg:taller1

Tabla de Contenidos

Clase 1

Plan para hoy

  • Introducción al uso de Hugs
  • Cómo escribir programas Haskell
  • Escribiendo los primeros programas

Clase

Hugs es un intérprete del lenguaje funcional puro Haskell.
Durante este taller escribiremos, probaremos y utilizaremos los programas funcionales que se dan en el teórico.

A Hugs se lo invoca desde la línea de comandos o picando sobre el ícono 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.

[nicolasw@azul Taller]$ hugs
__   __ __  __  ____   ___      _________________________________________
||   || ||  || ||  || ||__      Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__||  __||     Copyright (c) 1994-2005
||---||         ___||           World Wide Web: http://haskell.org/hugs
||   ||                         Report bugs to: hugs-bugs@haskell.org
||   || Version: March 2005     _________________________________________

Haskell 98 mode: Restart with command line option -98 to enable extensions

Type :? for help
Hugs.Base>

De este modo Hugs se convierte en una calculadora, esperando que se introduzca una expresión para evaluarla e imprimir el resultado, y luego volver a pedir una expresión (lazo leer-evaluar-imprimir).
Gracias al preludio standard tenemos muchas funciones ya definidas.

Hugs.Base> 21+21
42
Hugs.Base> 2*4 == 10 `div` 5 && True
False
Hugs.Base> [2,3,5,7,11]++[1,2]
[2,3,5,7,11,1,2]
Hugs.Base> reverse "dabale arroz a la zorra el abad"
"daba le arroz al a zorra elabad"

Este ciclo continúa indefinidamente hasta que pidamos la salida del intérprete con CTRL-D o con el comando

Hugs.Base> :q
[Leaving Hugs]
[nicolasw@azul Taller]$

Para poder dar nuevas definiciones y/o funciones necesitamos escribir un programa funcional o script Haskell.
Un programa funcional es un archivo con terminación .hs donde se escriben en texto plano todas las definiciones que conforman el programa funcional.

A manera de ejemplo realicemos un ciclo de creación-carga-prueba-modificación-recarga, con el Ejercicio 8.3 del apunte Extracto del Cálculo de Programas.

Para crear un script basta con invocar el comando para editar un (nuevo) archivo :e ejercicios8.hs. Una posible solución para el problema de la función signo es la siguiente:

sgn :: Int -> Int
sgn x   | 0<x   = 1
        | x<0   = -1
        | x=0   = 0

Luego de salvar el programa y cargarlo, el intérprete indica un error pues = es el símbolo de definición, mientras que la comparación es ==.

Hugs.Base> :e ejercicios8.hs
Hugs.Base> :l ejercicios8.hs
ERROR "ejercicios8.hs":4 - Syntax error in input (unexpected `=')

Las traducciones son más o menos directas, de todas formas preparamos una tabla de Traducción de Cálculo de Programas a Haskell.

Volvemos a editar el script con :e (el nombre ya no lo necesitamos ya que tenemos cargado este script) y corregimos x=0 por x==0. Podemos probar la nueva función para ganar confianza en su corrección.

Main> sgn 1
1
Main> sgn 0
0
Main> sgn -1
ERROR - Cannot infer instance
*** Instance   : Num (Int -> Int)
*** 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   : Fractional Int
*** Expression : sgn 1.1

Main> sgn (-1
ERROR - Syntax error in expression (unexpected end of input)

Main> map sgn [-10..10]
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,1,1,1,1,1,1,1,1,1]

Notamos los distintos tipos de errores que se producen por problemas de

  • Precedencia
  • Tipos
  • Sintáxis

A manera de ejemplo veamos el ejercicio 8.7, donde tenemos que definir una función muy útil para cualquier aparato que maneje un calendario (relojes, celulares, PDAs, computadoras, DVD-R, etc.). La signatura 1) 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 bisiesto:

La regla completa para los años bisiestos según el calendario Gregoriano es:
  Un año es bisiesto si es divisible por 4, excepto aquellos divisibles por 100 pero no por 400.

Entonces podemos seguir agregando definiciones de funciones a nuestro archivo ejercicios8.hs con el comando :e. Veamos tres versiones distintas 2).

La del viejo programadora/or

bisiesto'' :: Int -> Bool
bisiesto'' n = if  n `mod` 4 /= 0 then False
                else if n `mod` 100 /= 0 then True
                        else if n `mod` 400 == 0 then True
                                else False

El que está aprendiendo Haskell

bisiesto' :: Int -> Bool
bisiesto' n     | n `mod` 4 /= 0 = False
                | n `mod` 4 == 0 = n `mod` 100 /= 0 || n `mod` 400 == 0

El que cursó Introducción a los Algoritmos ;-)

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 filter para que obtener solo los años bisiestos desde 1945 al 2006.

Main> filter bisiesto [1945..2006]
[1948,1952,1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004]
Main> filter bisiesto' [1945..2006]
[1948,1952,1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004]
Main> filter bisiesto'' [1945..2006]
[1948,1952,1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996,2000,2004]

Vemos que las tres funciones operan correctamente en el rango de números dados 3).

Ejercicios

Para realizar en lo que resta de la clase.

  • Ejercicio 8.7

Definir la función edad : (Nat, Nat, Nat) → (Nat, Nat, Nat) → Int que dadas dos fechas indica los años transcurridos entre ellas. Por ejemplo edad.(20,10,1968).(30,4,1987) = 18

  • Ejercicio 8.8

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:
area.h.b.d = 2 ∗ frente + 2 ∗ lado + 2 ∗ arriba
|[ …aca va la definicion… ]|
donde frente, lado y arriba son las caras frontal, lateral y superior del prisma respectivamente.

1)
Signatura es el nombre de la función junto al tipo de sus parámetros y resultado
2)
Esto es una mala copia de The Evolution of a Haskell Programmer
3)
No queremos decir que sean correctas en su totalidad, solo decimos que en ese rango no tienen fallas
introalg/taller1.txt · Última modificación: 2018/08/10 03:03 por 127.0.0.1