En primer lugar, el mundo real Haskell , que estoy leyendo, dice que nunca usefoldl y en su lugar use foldl'. Entonces confío en eso.  
Pero estoy nebuloso sobre cuándo utilizar foldrvs foldl'. Aunque puedo ver la estructura de cómo funcionan de manera diferente frente a mí, soy demasiado estúpido para entender cuándo "cuál es mejor". Supongo que me parece que realmente no debería importar cuál se usa, ya que ambos producen la misma respuesta (¿no?). De hecho, mi experiencia previa con esta construcción es de Ruby injecty Clojure reduce, que no parecen tener versiones "izquierda" y "derecha". (Pregunta secundaria: ¿qué versión usan?)  
¡Cualquier idea que pueda ayudar a un tipo con problemas de inteligencia como yo sería muy apreciada!
fuente

fodlWhile); 2. conviértalo en un escaneo izquierdo (scanl) y deténgalo conlast . takeWhile po similar. Uh, y 3. usomapAccumL. :)foldlque recoge su resultado general y lo produce solo después de que todo el trabajo haya terminado y no haya más pasos para realizar. Entoncesfoldl (flip (:)) [] [1..3] == [3,2,1], por ejemplo , entoncesscanl (flip(:)) [] [1..] = [[],[1],[2,1],[3,2,1],...]... IOW,foldl f z xs = last (scanl f z xs)y las listas infinitas no tienen un último elemento (que, en el ejemplo anterior, sería una lista infinita, desde INF hasta 1).foldrSe ve como esto:foldlSe ve como esto:Contexto: Doblar en la wiki de Haskell
fuente
Su semántica difiere, por lo que no puedes simplemente intercambiar
foldlyfoldr. El primero dobla los elementos desde la izquierda, el otro desde la derecha. De esa manera, el operador se aplica en un orden diferente. Esto es importante para todas las operaciones no asociativas, como la resta.Haskell.org tiene un artículo interesante sobre el tema.
fuente
En breve,
foldres mejor cuando la función del acumulador es perezosa en su segundo argumento. Lea más en Stack Overflow de Haskell wiki (juego de palabras).fuente
La razón
foldl'preferidafoldlpara el 99% de todos los usos es que puede ejecutarse en espacio constante para la mayoría de los usos.Toma la función
sum = foldl['] (+) 0. Cuandofoldl'se usa, la suma se calcula inmediatamente, por lo que la aplicaciónsuma una lista infinita se ejecutará para siempre, y muy probablemente en un espacio constante (si está usando cosas comoInts,Doubles,Floats.IntegerS usará más que un espacio constante si el el número se hace mayor quemaxBound :: Int).Con
foldl, se crea un thunk (como una receta de cómo obtener la respuesta, que puede evaluarse más tarde, en lugar de almacenar la respuesta). Estos thunks pueden ocupar mucho espacio, y en este caso, es mucho mejor evaluar la expresión que almacenar el thunk (lo que lleva a un desbordamiento de pila ... y te lleva a ... oh, no importa)Espero que ayude.
fuente
foldlno hace más que aplicar constructores a uno o más de sus argumentos.foldles realmente la mejor opción? (Al igual que las listas infinitas cuandofoldres la elección incorrecta, en cuanto a optimización.)foldrser la elección incorrecta para listas infinitas. De hecho, no debe usarfoldlofoldl'para listas infinitas. Vea el wiki de Haskell sobre desbordamientos de pilaPor cierto, los de Ruby
injecty Clojurereducesonfoldl(ofoldl1, dependiendo de la versión que uses). Por lo general, cuando sólo hay un formulario en un idioma, es una izquierda pliegue, incluyendo Pythonreduce, PerlList::Util::reduce, C ++ 'saccumulate, C #' sAggregate, Smalltalkinject:into:, PHParray_reduce, MathematicaFold, etc. de Common Lispreducepor defecto a la izquierda veces, pero hay una opción para el derecho pliegue.fuente
reduceno es vago, por lo quefoldl'muchas de las consideraciones aquí no se aplican.foldl', ya que son idiomas estrictos, ¿no? De lo contrario, ¿eso no significará que todas esas versiones causan desbordamientos de pila como lofoldlhace?Como señala Konrad , su semántica es diferente. Ni siquiera tienen el mismo tipo:
Por ejemplo, el operador de lista append (++) puede ser implementado con
foldrcomomientras
le dará un error de tipo.
fuente
foldl subtract 0 [1, 2, 3, 4]evalúa a-10, mientras quefoldr subtract 0 [1, 2, 3, 4]evalúa a-2.foldles en realidad0 - 1 - 2 - 3 - 4mientrasfoldres4 - 3 - 2 - 1 - 0.foldr (-) 0 [1, 2, 3, 4]es-2yfoldl (-) 0 [1, 2, 3, 4]es-10. Por otro lado,subtractestá al revés de lo que podría esperar (subtract 10 14es4), así quefoldr subtract 0 [1, 2, 3, 4]es-10yfoldl subtract 0 [1, 2, 3, 4]es2(positivo).