Questa è una funzionalità del compilatore GHC. Fondamentalmente, GHC può riconoscere quando un elenco viene utilizzato in una "pipeline" e può convertire l'intero costrutto nell'equivalente di uno while
-loop in C che non assegna affatto un elenco.
Il motivo per cui questo funziona con foldr
e non foldl
dipende dalla funzione g
che si sta utilizzando nell'esempio. Dal foldr
, al posto di , si accumula il risultato della funzione data come parametro (alias: foldl
necessita dell'intera lista prima che possa iniziare effettivamente la valutazione della funzione g
, quindi crea un enorme "thunk" di funzioni non valutate e l'ultimo elemento della lista come risultato - ecco perché in questo caso usa molta più memoria - mentre foldr
può iniziare a valutare g
non appena riceve un input di lista), è chiamato "strict" nel suo accumulatore, e alcune supposizioni possono essere fatte dal compilatore che può portare a ottimizzazioni.
Se, per esempio, la funzione g
produce un valore che è un elenco, può continuare la suddetta strategia di ottimizzazione "pipeline", in pratica trattando il foldr
come un map
e rendendo l'intero costrutto (dalla generazione dell'elenco elencare consumo) in un ciclo rigoroso. Questo è possibile solo perché lo foldr
produce esattamente un elemento di lista per ogni elemento di lista che consuma, il che non è garantito a foldl
(specialmente per gli elenchi infiniti).
grazie. Ho scelto questa risposta perché distingue chiaramente tra foldr e foldl. – vis