foldr es una cosa fácil:
foldr :: (a->b->b) -> b -> [a] -> b
Se necesita una función que es de alguna manera similar a (:),
(:) :: a -> [a] -> [a]
y un valor que es similar a la lista vacía [],
[] :: [a]
y reemplaza cada uno: y [] en alguna lista.
Se ve así:
foldr f e (1:2:3:[]) = 1 `f` (2 `f` (3 `f` e))
Usted puede imaginar foldr como un estado-máquina-evaluador, también:
f es la transición,
f :: input -> state -> state
y e es la estado de inicio
e :: state
foldr (foldRIGHT) se ejecuta la máquina de estados con el f de transición y el estado de inicio e sobre la lista de entradas, comenzando en el extremo derecho.Imagina f en notación infija cuando el pacman viene de-DERECHO.
foldl (foldLEFT) hace lo mismo desde-IZQUIERDA, pero la función de transición, escrita en notación infija, toma su argumento de entrada desde la derecha. Entonces la máquina consume la lista comenzando en el extremo izquierdo. Pacman consume la lista desde-IZQUIERDA con la boca abierta hacia la derecha, debido a la boca (b-> a-> b) en lugar de (a-> b-> b).
foldl :: (b->a->b) -> b -> [a] -> b
Para aclarar esto, imaginemos el signo menos funcionan como transición:
foldl (-) 100 [1] = 99 = ((100)-1)
foldl (-) 100 [1,2] = 97 = ((99)-2) = (((100)-1)-2)
foldl (-) 100 [1,2,3] = 94 = ((97)-3)
foldl (-) 100 [1,2,3,4] = 90 = ((94)-4)
foldl (-) 100 [1,2,3,4,5] = 85 = ((90)-5)
foldr (-) 100 [1] = -99 = (1-(100))
foldr (-) 100 [2,1] = 101 = (2-(-99)) = (2-(1-(100)))
foldr (-) 100 [3,2,1] = -98 = (3-(101))
foldr (-) 100 [4,3,2,1] = 102 = (4-(-98))
foldr (-) 100 [5,4,3,2,1] = -97 = (5-(102))
Es posible que desee utilizar foldr en situaciones en las que la lista puede ser infinita, y donde la evaluación debe ser perezoso:
foldr (either (\l (ls,rs)->(l:ls,rs))
(\r (ls,rs)->(ls,r:rs))
) ([],[]) :: [Either l r]->([l],[r])
y probablemente quiera utilizar la versión estricta de foldl, que es foldl', cuando se consume toda la lista para producir su salida. Se podría realizar mejor y desee evitar tener pila desbordamiento o excepciones fuera de la memoria (dependiendo del compilador), debido a las largas listas extremas en combinación con la evaluación perezosa:
foldl' (+) 0 [1..100000000] = 5000000050000000
foldl (+) 0 [1..100000000] = error "stack overflow or out of memory" -- dont try in ghci
foldr (+) 0 [1..100000000] = error "stack overflow or out of memory" -- dont try in ghci
El primero -paso a paso - crea una entrada de la lista, la evalúa y la consume.
El segundo crea primero una fórmula muy larga, desperdiciando memoria con ((... ((0 + 1) +2) +3) + ...), y luego evalúa todo.
El tercero como el segundo, pero con la otra fórmula.
+1 para explicar la semántica y dar una analogía. Las otras respuestas hasta ahora solo dan una reducción formal, que es importante, pero para la comprensión a nivel conceptual es aún más importante en mi humilde opinión. – thSoft