foldl
とfoldr
の違いはループの方向だけですか?方向だけでなく、彼らがしたことにも違いがあると思いましたか?
関数が結合的でない場合(つまり、式を括弧で囲む方法が重要な場合)には違いがあります。たとえば、foldr (-) 0 [1..10] = -5
ただしfoldl (-) 0 [1..10] = -55
。
小規模では、10-(20-(30))
が_((10)-20)-30
_と同じではないためです。
_(+)
_は連想的であるため(部分式を追加する順序は関係ありません)、foldr (+) 0 [1..10] = 55
およびfoldl (+) 0 [1..10] = 55
。 _(++)
_は別の連想操作です。なぜなら、xs ++ (ys ++ zs)
は_(xs ++ ys) ++ zs
_と同じ答えを与えるからです(最初のほうが高速ですが、foldl (++)
を使用しないでください。
一部の機能は一方向にしか機能しません。foldr (:) :: [a] -> [a] -> [a]
しかしfoldl (:)
はナンセンスです。
Cale Gibbardの図をご覧ください( wikipediaの記事 );まったく異なるデータのペアでf
が呼び出されることがわかります。
もう1つの違いは、リストの構造と一致するため、foldr
は遅延評価にとってより効率的であることが多く、f
が厳密でない限り、無限リストで使用できることです。 2番目の引数(_(:)
_または_(++)
_など)。 foldl
がより良い選択であることはめったにありません。 foldl
を使用している場合、通常は_foldl'
_を使用する価値があります。これは厳密であり、中間結果の長いリストの作成を停止するためです。 (このトピックの詳細は、 この質問 への回答にあります。)