Haskell Hero
Haskell Hero es un manual interactivo del lenguaje Haskell para principiantes.
|
Tipos IICreamos cajas nuevasComo ya hemos visto en la lección Tipos I, Haskell dispone de una caja de todos números enteros, una caja de todos caracteres o por ejemplo una caja de dos valores booleanos. A veces es útil crear una caja nueva y en esta poner valores con que queremos trabajar. EjemploCread un tipo que va a contener todos los cuadrados indicados por la longitud de su lado y todos los rectángulos indicados por las longitudes de su anchura y altura.
Vamos a llamar nuestro tipo por ejemplo
Por ejemplo un cuadrado con la longitud de lado 4 será
Un rectángulo de anchura 7 y altura 2 será
En general queremos crear una caja data Obrazec = Cuadrado Integer | Rectangulo Integer IntegerNota: Si quisiéramos trabajar con figuras que no tienen dimensiones de números enteros, en vez de Integer usaríamos Float o Double .
Ahora sabemos como definir el tipo
Podríamos por ejemplo crear un tipo data Diccionario = Palabra StringAquí podemos sustituir String por cualquiera cadena. Este tipo contiene por ejemplo valores:
Palabra "Hola" Palabra "Haskell" Palabra "&@#Đđ" Trabajamos con cajas nuevasAhora cuando tenemos la caja de todos los cuadrados y rectángulos, podemos trabajar con ella de la misma manera como con otros tipos. Ejemplo
Definid funciones
Primero tenemos que poner nuestra definición del tipo data Figura = Cuadrado Integer | Rectangulo Integer Integer
Las dos funciones serán de tipo perimetro :: Figura -> Integer superficie :: Figura -> Integer
Ahora la definición propia. Todos sabemos que el perímetro de un cuadrado con la longitud de lado perimetro :: Figura -> Integer perimetro (Cuadrado x) = 4 * x
¡Cuidado con los paréntesis! En la anotación de tipo indicamos que la función perimetro Cuadrado x = 4 * xHugs identificaría el constructor Cuadrado y la variable x como dos parámetros para la función perimetro . La función perimetro puede, no obstante, tomar solo un valor de tipo Figura .
A esta definición podemos añadir también el perímetro de rectángulo. Sabemos que el perímetro de rectángulo de anchura perimetro :: Figura -> Integer perimetro (Cuadrado x) = 4 * x perimetro (Rectangulo x y) = 2 * (x + y)
Análogamente definimos la función superficie :: Figura -> Integer superficie (Cuadrado x) = x ^ 2 superficie (Rectangulo x y) = x * y Cuando tenemos las funciones definidas y preguntamos a Hugs qué es el perímetro del rectángulo 5 x 3, nos dice correctamente que 16. perimetro (Rectangulo 5 3) ~> 2 * (5 + 3) ~> 2 * 8 ~> 16 Tipos recursivos
Ahora ya sabemos como definir un tipo simple. Sin embargo, algunas veces vamos a necesitar un tipo más complejo. Por ejemplo quisiéramos crear un tipo Zero -- cero Succ Zero -- el sucesor de cero - dos Succ (Succ Zero) -- el sucesor del sucesor de cero - dos Succ (Succ (Succ Zero)) -- el sucesor del sucesor del sucesor de cero - tres ...¿Cómo definir un tal tipo? Tenemos que describir todos sus valores. En el ejemplo del párrafo anterior los valores de tipo Figura fueron o Cuadrado Integer o Rectangulo Integer Integer donde Integer se podía sustituir por cualquier número entero. Aquí tenemos dos formas:
Donde data Nat = Zero | Succ NatUn tipo definido de esta manera solamente indica la estructura del almacenamiento de datos en la memoria. No se dice en ningún lugar como imprimir los valores si es necesario. La manera más fácil como hacerlo es añadir la cadena deriving Show a la definición de tipo. ¡Cuidado con la minúscula 'd' y la mayúscula 'S'! La definición de tipo Nat con la posibilidad de imprimir los valores será la siguiente:
data Nat = Zero | Succ Nat deriving Show Funciones con tipos recursivos
Aquí vamos a definir una función simple con el tipo Ejemplo
¿Cómo empezar? Tenemos que acordarnos de que podemos hacer con los valores de tipo
Podemos entonces definir la función masNat :: Nat -> Nat -> Nat masNat Zero y = y masNat (Succ x) y = masNat x (Succ y) |