質問

私は読んでいます。

まず、の実世界Haskellはの、foldlを使用せず、代わりにfoldl'を使用しないために述べています。だから私はそれを信頼しています。

しかし、私はfoldrfoldl'を使用する際にかすみました。私は違った私の前にレイアウトされ、彼らがどのように動作するかの構造を見ることができますが、私はときに理解するにはあまりにも愚かだ「優れています。」私は彼らの両方が同じ答えを作るとして、それは本当に問題で、使用されるべきではありませんどのようにそれは私には思われると思います(そうではありません?)。実際には、この構築物での私の過去の経験は、Rubyのinjectと「左」と「右」のバージョンているようには見えませんClojureののreduce、からです。 (サイド質問:バージョン、彼らが使うのですか?)

私のような知性チャレンジソートははるかに高く評価されるだろうことができます任意の洞察力!

役に立ちましたか?

解決

foldr f x ysは、

のように見えますys = [y1,y2,...,yk]のための

再帰

f y1 (f y2 (... (f yk x) ...))

foldl f x ysのための再帰は、

のように見えるのに対し、
f (... (f (f x y1) y2) ...) yk

ここでの重要な違いは、f x yの結果はxの値のみを使用して計算することができるならば、その後、foldr「のリスト全体を調査する必要がないということです。たとえば、

foldr (&&) False (repeat False)

戻る

一方False
foldl (&&) False (repeat False)

終了したことがありません。 (注:repeat Falseは、すべての要素がFalseある無限のリストを作成する)

一方、foldl'尾再帰と厳密です。あなたはどんなリスト全体をトラバースしないする必要がありますことがわかっている場合(例えば、リスト内の数字を合計する)、そしてfoldl'は、より省スペース(そしておそらく、時間)foldrよりも効率的です。

他のヒント

foldrは次のようになります:

右倍見える化

foldlは次のようになります:

左倍の可視化

コンテキスト:のHaskellウィキにを折る

その意味では、あなただけのfoldlfoldrを交換することはできませんので、異なっています。一つは、左、右から他の要素を折りたたん。その方法は、オペレータは異なる順序で適用されます。これは、減算など、すべての非会合の操作のために重要です。

Haskell.orgするのhref = "http://haskell.org/haskellwiki/Foldr_Foldl_Foldl%27 <興味深いがあります"REL =" noreferrer ">テーマに関する記事。

まもなく、foldrはアキュムレータ機能が第2引数に怠惰なときに優れています。 Haskellのwikiのスタックオーバーフローを(しゃれが意図し)ます。

続きを読みます

foldl'は、すべての使用の99%のためfoldlするのが好ましい理由は、ほとんどの用途のために一定の間隔で実行することができるということです。

関数sum = foldl['] (+) 0してください。 foldl'を使用する場合は、あなたがsums、Ints、Doublesのようなものを使用している場合、合計は(すぐに計算されるので、無限リストにFloatを適用するだけで永遠に実行され、一定の間隔で最も可能性が高い。Integersが一定間隔以上に使用されます数maxBound :: Intよりも大きくなった場合)。

foldlでは、サンクは、(むしろ答えを保存するよりも、後で評価できる答えを、取得する方法のレシピのように)構築されます。これらのサンクは、多くのスペースを取ることができ、この場合には、それはサンク保存するよりも、表現を評価するために非常に良いでしょう(スタックオーバーフローにつながると...そしてあなたは...ああ気にしないにつながる)

希望に役立ちます。

ちなみに、RubyのinjectとClojureののreducefoldl(またはfoldl1、あなたが使用しているバージョンによって異なります)されています。一形態のみが言語であった場合に通常、それはなど、Pythonのreduce、PerlのList::Util::reduce、C ++のaccumulate、C#のAggregate、Smalltalkのinject:into:、PHPのarray_reduce、MathematicaのFold含む左倍、あるCommon Lispのreduceのデフォルトは左倍が、右の折り畳みのためのオプションがあります。

コンラートのが指摘するように、彼らのセマンティクス異なっています。彼らも同じ型を持っていない。

ghci> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b
ghci> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
ghci> 

たとえば、リスト追記演算子(++)は

のようfoldrで実施することができます
(++) = flip (foldr (:))

(++) = flip (foldl (:))

あなたのタイプのエラーになります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top