2016-06-22 9 views
5

私の理解では、foldlfoldrは以下のように実行されるということです。なぜfoldlはandFn関数で短絡していないのですか?

foldl f a [1..30] =>(f (f (f ... (f a 1) 2) 3) ... 30)

foldr f a [1..30] =>(f 1 (f 2 (f 3 (f ....(f 30 a)))))..)

..だからfoldr (&&) False (repeat False)(&&) False ((&&) False (....))が最初に見たように、最も外側のfが見shortciruitすることができます2番目の引数(大きなサンク)を評価する必要はありません。

はそう

andFn :: Bool -> Bool -> Bool 
andFn _ False = False 
andFn x True = x 

foldl andFn True (repeat False) -- => 

-- (andFn (andFn ...(andFn True False) ... False) False) 
-- ^^ outermost andFn 

で何が起こるかしかし、これは永遠に取っています。

私はここで何が起こっている他に何

... outermost andFnは、第二引数にパターンマッチングによって、答えはFalseであることを知っているだろうと思いましたか?

答えて

14

foldrfoldlの間には、andFnの引数の順序よりも大きな違いがあります。

foldr f z (x:xs) = f x (foldr f z xs) 
foldl f z (x:xs) = foldl f (f z x) xs 

すぐfに制御を移す方法foldrお知らせ:fは怠惰であるならば、それはfoldr f z xsの計算を避けることができます。

代わりに、foldl転送がするように制御する... foldl:基本ケースが

foldl f z [] = z  -- z contains the chained f's, which NOW get evaluated 

に達したときに機能fにのみ使用されて起動しますしたがってfoldl f z infiniteListは関係なく、何であるかf常に発散、意志実際の計算が行われる前に、infiniteList全体を完全に反復する必要があります。 (オフトピック:これは、それが動作しても、なぜあるfoldlは、しばしばひどい性能を有し、かつfoldl'は実際にはより使用されている。)特に

、掲載例

foldl andFn True (repeat False) -- => 
-- (andFn (andFn ...(andFn True False) ... False) False) 
-- ^^ outermost andFn 

が部分的に間違っています。 「最も外側のandFn」は、実際に最後のであり、すなわち最後の要素に関連するもの、repeat Falseである。しかし、そのような獣はありません。

関連する問題