2011-10-31 14 views
13

なぜ以下のHaskellコードが終了しない:なぜこのHaskellコードは終了しないのですか?

foldr (||) True $ repeat False -- never terminates 

このようなものがない場合:

foldr (||) False $ repeat True -- => True 

私には、それが終了していないのよりトラブルになりそうだ第二の発現です。何がHaskellの遅延評価の私の見解が悪いですの?

+0

これらの種類の問題には常にstepevalを使用できます。解読までに2秒かかるが、参考になるかもしれない。 http://bm380.user.srcf.net/cgi-bin/stepeval.cgi?expr=foldr+%28%7C%7C%29+True+%24+repeat+False – gatoatigrado

+0

私はstepevalを書いており、その式を評価していません正しく!それはいくつかのバグを持っています、私は恐れています(この場合、それはまだそれを必要としても 'let'を忘れてしまいます) –

答えて

18

あなたの怠け者の理解は正しいと思いますが、foldrではありません。あなたは私たちが||が終了に到達するために「を探して」いるTruez)ができなくなりますご覧のように、あなたの表現

foldr (||) True $ repeat False -- never terminates 

を見て、その「specification

foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...) 

を見てみましょうリスト全体が消費されるまで達する。リストが無限であるので、それは起こりません。

実際に終了する例についても説明します。

+0

確かに、私は、怠惰な評価ではなく、間違いのfoldrだった! –

13

False || (False || (False || ...))に展開し、2番目はTrue || (True || (True || ...))に展開します。 foldrの第2引数は、赤ん坊です。||の最も内側のアプリケーションに表示されます。最も外側のアプリケーションではないため、実際には到達することはできません。

9

手動foldrを展開する場合、問題は、非常に明白である:

foldr (||) True $ repeat False == False || (False || (False (False || ... True))) 

だから、最終的なFalseを得るために、コードは、その(nonexistant)最後までリストを評価しなければなりませんでした。 2番目の例では、Trueを繰り返すので、短絡の評価が可能です。怠惰な評価から魔法を期待しないでください!

+2

あなたは展開中にTrueとFalseを入れ替えました。 –

+0

@ダニエルありがとう。それはベルリンでは遅くここにあります... – fuz

3

Aはまだあなたのために別の洞察力が||はHaskellでは可換ではないということです、それは偏ったです:

Prelude> undefined || True 
*** Exception: Prelude.undefined 
Prelude> True || undefined 
True 

だから、数学とは異なり、||flip (||)は異なる機能です。例えば。旧終了

foldr (||) False $ repeat Truefoldr (flip (||)) False $ repeat True

を比較するが、後者はそうではありません。

+0

ありがとうございます。それは私にとって本当に別の驚きです! –

関連する問題