web-dev-qa-db-ja.com

Haskell-foldlとfoldr?

foldlfoldrの違いはループの方向だけですか?方向だけでなく、彼らがしたことにも違いがあると思いましたか?

50
Lethi

関数が結合的でない場合(つまり、式を括弧で囲む方法が重要な場合)には違いがあります。たとえば、
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が呼び出されることがわかります。
foldrfoldl

もう1つの違いは、リストの構造と一致するため、foldrは遅延評価にとってより効率的であることが多く、fが厳密でない限り、無限リストで使用できることです。 2番目の引数(_(:)_または_(++)_など)。 foldlがより良い選択であることはめったにありません。 foldlを使用している場合、通常は_foldl'_を使用する価値があります。これは厳密であり、中間結果の長いリストの作成を停止するためです。 (このトピックの詳細は、 この質問 への回答にあります。)

104
AndrewC