¿Puede un programa decirte que está mal antes de ejecutarse?
Una hoja de cálculo que suma un nombre y un número da una respuesta rara, y lo descubres más tarde. Haskell te pide que digas qué tipo de cosa recibe y devuelve cada función, y lo comprueba antes de que se ejecute nada. Así toda una clase de errores no puede ocurrir.
Al final de esta lección
Nota
Puedo leer y ejecutar una función de Haskell y decir qué me cuenta su tipo.
Palabras clave
- Función: algo que recibe un valor y devuelve otro.
- Tipo: la clase de un valor, como
Intpara un número entero oStringpara texto. - Firma de tipo: la línea que da su tipo a una función, como
square :: Int -> Int. - Lista: varios valores de un mismo tipo, en orden, escritos
[1, 2, 3]. - Pliegue (fold): una forma de combinar todos los elementos de una lista en un solo valor.
Para empezar: lo que ya sabes
Nota
Responde mentalmente. 1. En matemáticas, si f(x) = x * x, ¿cuánto es f(5)? 2. ¿Es 7 la misma clase de cosa que "seven"? 3. ¿Cuál es la suma de la lista 1, 2, 3? Respuestas: 25; no, uno es un número y el otro es texto; 6.
Antes de empezar
Nota
Pulsa Iniciar el laboratorio en la barra de arriba de la lección y espera a que diga que está en marcha. Hay un solo contenedor, haskell. No se abre nada en un navegador, así que usa el terminal, donde docker exec haskell ejecuta una orden dentro de él. El compilador tarda un par de segundos en arrancar cada vez. Todo lo que se imprime está en inglés, sea cual sea el idioma de esta página. Cada botón Ejecutar de abajo escribe su orden en el terminal de tu laboratorio, una detrás de otra en la misma sesión. Para verlas o escribir las tuyas, pulsa Abrir terminal (pestaña nueva) en la barra.
Una función tiene una firma de tipo
Esta orden imprime el primer archivo. La línea square :: Int -> Int es una firma de tipo. Léela así: «square recibe un Int y devuelve un Int». La línea siguiente dice cómo: square n = n * n. Aquí una función no tiene efectos secundarios: dale el mismo valor y obtendrás la misma respuesta. -- empieza un comentario.
docker exec haskell cat Basics.hsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecutar un archivo, o preguntar por una función
runghc ejecuta el archivo. Su main imprime tres líneas: Hello, Haskell!, luego 49 y luego (True,False). Las opciones ghc -e calculan una expresión con el archivo cargado: la primera pide el tipo de square e imprime square :: Int -> Int, y la segunda la llama e imprime 144.
docker exec haskell runghc Basics.hsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
docker exec haskell ghc -e ":type square" Basics.hsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
docker exec haskell ghc -e "square 12" Basics.hsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Comprueba
Consejo
¿Qué te dice isEven :: Int -> Bool antes de leer el código? Respuesta: que recibe un número entero y devuelve True o False.
Una lista se trabaja con funciones
map aplica una función a cada elemento y filter se queda con los que pasan una prueba. La primera orden eleva al cuadrado de 1 a 5 con square y los suma con sum: imprime 55. La segunda se queda con los pares de 1 a 10 e imprime [2,4,6,8,10]. Ninguna cambia la lista original: cada una da un valor nuevo.
docker exec haskell ghc -e "sum (map square [1 .. 5])" Basics.hsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
docker exec haskell ghc -e "filter even [1 .. 10]"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Una función puede llamarse a sí misma, y un pliegue lo hace por ti
mySum en Fold.hs suma una lista sumando el primer elemento a la suma del resto, y parando en la lista vacía. Esta orden imprime 6. La segunda hace el mismo trabajo con el foldr incorporado, que pliega una lista en un solo valor: imprime 5050, la suma de 1 a 100.
docker exec haskell ghc -e "mySum [1, 2, 3]" Fold.hsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
docker exec haskell ghc -e "foldr (+) 0 [1 .. 100]"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
El compilador comprueba los tipos
Esta orden le da texto a square en vez de un número. No se ejecuta nada. El compilador imprime un error que empieza por <interactive> y dice que no puede hacer coincidir el tipo [Char], que es texto, con Int. Lee el error desde arriba: nombra la parte de tu expresión que está mal. El código entre corchetes y la disposición pueden cambiar entre versiones.
docker exec haskell ghc -e "square \"two\"" Basics.hsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error frecuente
Advertencia
Mucha gente piensa que una firma de tipo es solo un comentario para el lector. No lo es. El compilador comprueba todas, y si el código no coincide, no se ejecuta nada. Escribe primero la firma cuando puedas: dice lo que querías, y el compilador te avisa cuando el código dice otra cosa.
Comprobación final
Consejo
Responde sin mirar atrás. 1. ¿Qué significa Int -> Bool? 2. ¿Qué da filter even [1 .. 10]? 3. ¿Cuándo encuentra el compilador un error de tipos: antes de que el programa se ejecute o después? 4. ¿Qué hace un pliegue con una lista? Respuestas: recibe un número entero y devuelve True o False; [2,4,6,8,10]; antes, así que no se ejecuta nada; combina todos los elementos en un solo valor.
Para docentes
Consejo
Esta lección es un pequeño ejemplo de lección que se hace en un laboratorio: los pasos y los botones Ejecutar son la lección, y el laboratorio es la copia de cada estudiante. El laboratorio es un contenedor con el compilador GHC y cuatro archivos pequeños, y nada aquí se corrige solo: el estudiante entrega las expresiones que probó con lo que imprimió cada una, una función propia con su tipo y una llamada que la muestre funcionando, y una frase sobre lo que dice una firma de tipo al lector. Puntos clave: 1. Una función recibe un valor y devuelve otro. 2. Una firma de tipo dice lo que una función recibe y devuelve. 3. Las listas se trabajan con funciones como map y filter. 4. Una función puede llamarse a sí misma, y un pliegue hace el mismo trabajo. 5. El compilador comprueba los tipos antes de que se ejecute nada. Error frecuente: tratar una firma como un comentario. Material: el laboratorio y su terminal. Consejo: pida a los estudiantes que escriban el tipo de una función antes que su cuerpo. Cada respuesta es exacta e igual cada vez; la primera orden tras arrancar tarda un par de segundos. Los nombres y los mensajes están en inglés, sea cual sea el idioma de la página.