La différence entre foldl
et foldr
est-elle juste la direction du bouclage? Je pensais qu'il y avait une différence dans ce qu'ils faisaient, pas seulement dans la direction?
Il y a une différence si votre fonction n'est pas associative (c'est-à-dire qu'elle importe de quelle manière vous mettez les expressions entre crochets), par exemple,foldr (-) 0 [1..10] = -5
mais foldl (-) 0 [1..10] = -55
.
À petite échelle, c'est parce que 10-(20-(30))
n'est pas la même chose que ((10)-20)-30
.
Alors que (+)
Est associatif (peu importe l'ordre dans lequel vous ajoutez des sous-expressions),foldr (+) 0 [1..10] = 55
et foldl (+) 0 [1..10] = 55
. (++)
Est une autre opération associative car xs ++ (ys ++ zs)
donne la même réponse que (xs ++ ys) ++ zs
(Bien que la première soit plus rapide - n'utilisez pas foldl (++)
.
Certaines fonctions ne fonctionnent que dans un sens:foldr (:) :: [a] -> [a] -> [a]
mais foldl (:)
n'a pas de sens.
Jetez un œil aux diagrammes de Cale Gibbard (tirés de article wikipedia ); vous pouvez voir f
être appelé avec des paires de données vraiment différentes:
Une autre différence est que, parce qu'il correspond à la structure de la liste, foldr
est souvent plus efficace pour une évaluation paresseuse, il peut donc être utilisé avec une liste infinie tant que f
n'est pas strict dans son deuxième argument (comme (:)
ou (++)
). foldl
n'est que rarement le meilleur choix. Si vous utilisez foldl
, cela vaut généralement la peine d'utiliser foldl'
Car il est strict et vous empêche de constituer une longue liste de résultats intermédiaires. (Plus d'informations sur ce sujet dans les réponses à cette question .)