foldr è una cosa facile:
foldr :: (a->b->b) -> b -> [a] -> b
Si prende una funzione che è in qualche modo simile a (:),
(:) :: a -> [a] -> [a]
ed un valore che è simile alla lista vuota [],
[] :: [a]
e sostituisce ciascuno: e [] in qualche elenco.
Ecco come si presenta:
foldr f e (1:2:3:[]) = 1 `f` (2 `f` (3 `f` e))
si può immaginare foldr alcuni state-machine-valutatore, anche:
f è la transizione,
f :: input -> state -> state
ed e è il stato di partenza.
e :: state
foldr (foldRIGHT) gestisce lo stato della macchina con la f transizione e lo stato di avvio e sopra l'elenco degli ingressi, iniziando all'estremità destra.Immagina la notazione infix come il pacman proveniente da -DEST.
foldl (foldLEFT) fa lo stesso da-sinistra, ma la funzione di transizione, scritto in notazione infissa, prende il parametro di input da destra. Quindi la macchina consuma la lista iniziando dall'estremità sinistra. Pacman consuma l'elenco da -L'ALTRO con una bocca aperta a destra, a causa della bocca (b-> a-> b) invece di (a-> b-> b).
foldl :: (b->a->b) -> b -> [a] -> b
Per chiarire questo punto, immaginiamo la funzione meno come di transizione:
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))
Probabilmente si desidera utilizzare foldr in situazioni, dove la lista può essere infinita, e dove la valutazione dovrebbe essere pigro:
foldr (either (\l (ls,rs)->(l:ls,rs))
(\r (ls,rs)->(ls,r:rs))
) ([],[]) :: [Either l r]->([l],[r])
E probabilmente desidera utilizzare la versione rigorosa della foldl, che è foldl', quando si consuma l'intera lista per produrre il suo output. Potrebbe funzionare meglio e potrebbe evitare di dover stack overflow o eccezioni out-of-memoria (a seconda del compilatore) a causa di lunghe liste estremi in combinazione con la valutazione pigra:
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
Il primo passo -step - crea una voce dell'elenco, la valuta e la consuma.
Il secondo crea una formula molto lunga prima, sprecando memoria con ((... ((0 + 1) +2) +3) + ...), e valuta tutto in seguito.
Il terzo come il secondo, ma con l'altra formula.
+1 per spiegare la semantica e dare un'analogia. Le altre risposte finora danno solo una riduzione formale, che è importante, ma per la comprensione a livello concettuale è ancora più importante IMHO. – thSoft