なぜ以下のHaskellコードが終了しない:なぜこのHaskellコードは終了しないのですか?
foldr (||) True $ repeat False -- never terminates
このようなものがない場合:
foldr (||) False $ repeat True -- => True
私には、それが終了していないのよりトラブルになりそうだ第二の発現です。何がHaskellの遅延評価の私の見解が悪いですの?
なぜ以下のHaskellコードが終了しない:なぜこのHaskellコードは終了しないのですか?
foldr (||) True $ repeat False -- never terminates
このようなものがない場合:
foldr (||) False $ repeat True -- => True
私には、それが終了していないのよりトラブルになりそうだ第二の発現です。何がHaskellの遅延評価の私の見解が悪いですの?
あなたの怠け者の理解は正しいと思いますが、foldr
ではありません。あなたは私たちが||
が終了に到達するために「を探して」いるTrue
(z
)ができなくなりますご覧のように、あなたの表現
foldr (||) True $ repeat False -- never terminates
を見て、その「specification」
foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)
を見てみましょうリスト全体が消費されるまで達する。リストが無限であるので、それは起こりません。
実際に終了する例についても説明します。
確かに、私は、怠惰な評価ではなく、間違いのfoldrだった! –
False || (False || (False || ...))
に展開し、2番目はTrue || (True || (True || ...))
に展開します。 foldr
の第2引数は、赤ん坊です。||
の最も内側のアプリケーションに表示されます。最も外側のアプリケーションではないため、実際には到達することはできません。
手動foldr
を展開する場合、問題は、非常に明白である:
foldr (||) True $ repeat False == False || (False || (False (False || ... True)))
だから、最終的なFalse
を得るために、コードは、その(nonexistant)最後までリストを評価しなければなりませんでした。 2番目の例では、True
を繰り返すので、短絡の評価が可能です。怠惰な評価から魔法を期待しないでください!
あなたは展開中にTrueとFalseを入れ替えました。 –
@ダニエルありがとう。それはベルリンでは遅くここにあります... – fuz
Aはまだあなたのために別の洞察力が||
はHaskellでは可換ではないということです、それは偏ったです:
Prelude> undefined || True
*** Exception: Prelude.undefined
Prelude> True || undefined
True
だから、数学とは異なり、||
とflip (||)
は異なる機能です。例えば。旧終了
foldr (||) False $ repeat True
とfoldr (flip (||)) False $ repeat True
を比較するが、後者はそうではありません。
ありがとうございます。それは私にとって本当に別の驚きです! –
これらの種類の問題には常にstepevalを使用できます。解読までに2秒かかるが、参考になるかもしれない。 http://bm380.user.srcf.net/cgi-bin/stepeval.cgi?expr=foldr+%28%7C%7C%29+True+%24+repeat+False – gatoatigrado
私はstepevalを書いており、その式を評価していません正しく!それはいくつかのバグを持っています、私は恐れています(この場合、それはまだそれを必要としても 'let'を忘れてしまいます) –