Haskell Hero
Haskell Hero es un manual interactivo del lenguaje Haskell para principiantes.
|
Programamos una calculadora¿Qué vamos a necesitar?
¿Qué es una calculadora? Es un aparato al que damos una expresión (por ejemplo Vamos a programar una calculadora que sabe sumar, restar y multiplicar. Necesitamos dos cosas para poderlo hacer:
Definimos expresiones de entrada
En la calculadora normal ponemos expresiones en forma Entonces vamos a crear un tipo nuevo que va a contener todos números enteros. data Expresion = Numero IntegerCon este hemos definido una caja que contiene valores Numero 1 , Numero 2 , Numero -5 , ...
Añadimos una expresión que representa la adición de expresiones: data Expresion = Numero Integer | Mas Expresion ExpresionEn esta caja hay por ejemplo expresiones siguientes: Mas (Numero 2) (Numero 5) Mas (Numero 4) (Numero 8) Mas (Numero 2) (Mas (Numero 2) (Numero 3)) De esta manera añadimos también expresiones que representan la resta y la multiplicación: data Expresion = Numero Integer | Mas Expresion Expresion | Menos Expresion Expresion | Multiplicado Expresion ExpresionEn esta caja ya estará también la expresión que representa 5 + 3 * 2 . Lo escribimos de manera siguiente:
Mas (Numero 5) (Multiplicado (Numero 3) (Numero 2)) Definimos una función de evaluaciónAhora ya tenemos definidas las expresiones y necesitamos una función que tome por ejemplo la expresión: Mas (Numero 5) (Multiplicado (Numero 3) (Numero 2))y la evalúe al número 11 . Pues empecemos.
Empezamos evaluando la expresión evalua :: Expresion -> Integer evalua (Numero x) = x¡Cuidado con los paréntesis! La función evalua es unaria, por eso tenemos que poner la expresión Numero x entre paréntesis para que la función la tome como un parámetro.
Después tenemos que definir la evaluación de la expresión de adición. Queremos que por ejemplo la expresión
La expresión
Entonces tenemos que añadir esta ecuación a la definición: evalua (Mas x y) = (evalua x) + (evalua y)De la misma manera definimos también la resta y la multiplicación: evalua (Menos x y) = (evalua x) - (evalua y) evalua (Multiplicado x y) = (evalua x) * (evalua y) La definición final será entonces la siguiente: evalua :: Expresion -> Integer evalua (Numero x) = x evalua (Mas x y) = (evalua x) + (evalua y) evalua (Menos x y) = (evalua x) - (evalua y) evalua (Multiplicado x y) = (evalua x) * (evalua y) La evaluación modelo
Vamos a evaluar la expresión evalua (Mas (Numero 5) (Multiplicado (Numero 3) (Numero 2))) ~> (evalua (Numero 5)) + (evalua (Multiplicado (Numero 3) (Numero 2))) ~> 5 + (evalua (Multiplicado (Numero 3) (Numero 2))) ~> 5 + ((evalua (Numero 3)) * (evalua (Numero 2))) ~> 5 + ( 3 * (evalua (Numero 2))) ~> 5 + ( 3 * 2 ) ~> 5 + 6 ~> 11 ¿Porqué lo hacemos?Podéis preguntar - ¿porqué lo hacemos? Hugs sabe sumar y restar, pues ¿por qué hacer tanto trabajo definiendo un tipo nuevo y todas las funciones?
Imaginemos que la multiplicación de números grandes es mucho más compleja que la adición. Por ejemplo la expresión Como hemos dicho al principio que la multiplicación de números grandes es mucho más complejo que la adición, podemos ver que la expresión (3 * 5) + (3 * 6) se evalúa más rápido que la expresión 3 * (5 + 6). Podríamos entonces convertir las expresiones en forma x * (y + z) en unas en forma (x * y) + (x * z) y solo después empezar a evaluar. ¿Qué será la función que realizará esta simplificación? simplifica :: Expresion -> Expresion simplifica (Multiplicado x (Mas y z)) = Plus (Multiplicado (simplifica x) (simplifica y)) (Multiplicado (simplifica x) (simplifica z)) simplifica _ = _Para la evaluación optimizada no usaremos entonces solamente la función evalua , sino la función compuesta (evalua . simplifica) .
|