¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Map, filter y fold en lugar de bucles

Después de esta lección: Puedo sustituir un bucle por map, filter o fold.

Lección de 55 min9 comandosLaboratorio de Haskell: programación funcional con funciones y tipos, en el navegador

Tres funciones que sustituyen casi todos los bucles

Map, filter y fold son tres funciones de Haskell que sustituyen casi todos los bucles sobre listas. Transforman cada elemento, se quedan con algunos o reducen la lista a un solo valor. Con ellas, "duplica cada precio, quédate con los caros y súmalos" cabe en una línea.

Verás cada una por separado y después las encadenarás.

Al final de esta lección

Nota

Puedo sustituir un bucle por map, filter o fold.

Palabras clave

PalabraQué significa
Mapaplica una función a cada elemento de una lista
Filterconserva los elementos que pasan una prueba
Foldreduce una lista a un solo valor
Acumuladorel valor que va creciendo mientras se recorre la lista
Orden superioruna función que recibe otra función como dato

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Map aplica una función a cada elemento

Map recibe una función y una lista. Devuelve otra lista de la misma longitud, con la función aplicada a cada elemento.

map (* 2) [1, 2, 3] da [2, 4, 6]. Es una función de orden superior: recibe otra función como dato. La lista original no cambia nunca; map construye una nueva.

Dobla cada número de una lista

Comando
docker exec haskell ghc -e "map (*2) [1, 2, 3]"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Cuenta las letras de cada palabra

Comando
docker exec haskell ghc -e "map length [\"pan\", \"leche\", \"huevos\"]"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Pregunta el tipo de map

Comando
docker exec haskell ghc -e ":type map"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Filter conserva lo que cumple una prueba

Filter recibe una prueba, una función que devuelve verdadero o falso, y una lista. Devuelve solo los elementos para los que la prueba es verdadera.

filter (> 10) [4, 12, 9, 15] da [12, 15]. La lista resultante puede ser más corta, o quedar vacía.

Quédate con los precios caros

Comando
docker exec haskell ghc -e "filter (> 10) [4, 12, 9, 15]"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Quédate con los números pares

Comando
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.

Fold reduce una lista a un solo valor

Fold recorre la lista y va combinando sus elementos con un acumulador. Recibe una función de dos datos, el valor inicial y la lista.

foldr (+) 0 [1 .. 5] da 15. Hay dos versiones. foldl empieza por la izquierda y foldr por la derecha. Con la suma da igual, pero con la resta no.

Ejemplo: foldl (-) 10 [1, 2, 3]

ElementoAcumulador antesCuentaAcumulador después
11010 - 19
299 - 27
377 - 34
Fin4No quedan elementosResultado: 4

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Suma los números del 1 al 5

Comando
docker exec haskell ghc -e "foldr (+) 0 [1 .. 5]"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Resta empezando por la izquierda

Comando
docker exec haskell ghc -e "foldl (-) 10 [1, 2, 3]"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

La misma resta, por la derecha

Comando
docker exec haskell ghc -e "foldr (-) 10 [1, 2, 3]"

Se 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 cree que foldl y foldr dan siempre lo mismo. Con la suma sí, porque da igual el orden. Con la resta no: los dos Runs anteriores dan 4 y -8. Cuando el orden importa, mira siempre desde qué lado empieza el fold.

Encadena filter, map y suma

Comando
docker exec haskell ghc -e "sum (map (* 3) (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.

Un bucle que hace las tres cosas

Código: python
# Un bucle que hace tres cosas a la vez: filtrar, transformar y reducir.
prices = [4, 12, 9, 15]
total = 0
for price in prices:
    if price > 10:
        total = total + price * 2
print(total)
# En Haskell: sum (map (* 2) (filter (> 10) prices))
# Cambia el 10 por un 8 y vuelve a ejecutar.

Para ir más lejos

Con fold se puede construir casi cualquier función de listas. foldr (:) [] [1, 2, 3] devuelve la misma lista, y foldl (flip (:)) [] [1, 2, 3] la devuelve al revés.

Prueba a escribir con my_fold una función que dé la longitud de una lista y otra que dé el mayor de una lista de números.

Sobre este laboratorio y su código: Laboratorio de Haskell: programación funcional con funciones y tipos, en el navegador

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.