これは、Haskellのfoldr関数を書くのが正しい方法ですか?
-
22-08-2019 - |
質問
私は、 YAHTの再帰的なデータ型のセクションからの練習をしていましたそして、(私は本当に最初はlistFoldr
とfoldl
の違いを理解していなかった主な理由は)ビットに挑戦foldr
機能を書きました。私は最終的にfoldr
機能が働いていた方法を正確に気づいたとき、私は、関数の引数のシンプルスワップはそれがlistFoldl
関数に私のlistFoldr
機能を変更するために必要なことと思いますすべてのだろうと判断します:
listFoldl f i [] = i
listFoldl f i (x:xs) = listFoldl f (f i x) xs
listFoldr f i [] = i
listFoldr f i (x:xs) = listFoldr f (f x i) xs
このは(私はこれ以上のテストをしました)仕事に表示されます:
Main> foldr (-) 4 [1, 2, 3]
-2
Main> listFoldr (-) 4 [1, 2, 3]
-2
しかし、運動のために与えられたソリューションにはかなりあります私より異なります。彼らのlistFoldl
は私と全く同じであるが、そのlistFoldr
を見ます:
listFoldr f i [] = i
listFoldr f i (x:xs) = f x (listFoldr f i xs)
優れている解決策、鉱山や彼ら?そのうちの一つが間違っていますか?
(私のテストでは、彼らの両方が...まったく同じ結果に終わります)解決
私は、あなたが「逆の順序」の要素を処理していると思うので、あなたは右ではありません。
あなたは、例えば、「注文事項」でこれを実証することができるはずです。例えば、のようなもの。
listfoldr f "" ["a", "b", "c"]
「F」は
の線に沿って関数でありますf s1 s2 = "now processing f(" @ s1 @ "," @ s2 @ ")\n"
ここで、「@」文字列追記演算子(私はそれがHaskellであるもの忘れ)です。あなたはそれが様々な引数で呼び出さなっているものをオーダー見ることができるようにポイントがちょうど「楽器」にする機能です。
(数学「4-1-2-3」は「4-3-2-1」と同じ答えを与えるため。これはあなたの例では現れなかったことに注意してください)
他のヒント
あなたの解決策は間違いなく間違っています。あなたは、単に機能foldl
は逆の順序で引数を取りするf
を実装しています。何が間違っているの例えば、foldr (:) []
は、リスト上の特定の機能のはずが、あなたの関数は、リストを反転させています。そこにあなたの関数がfoldr
は無限リストにどのように動作するかのように、foldr
ではない他の理由がたくさんあるとあなたにはありません。それは、彼らはあなたの例では同じであることを理由3 - (2 - (1 - 4)) == 1 - (2 - (3 - 4))
純粋な偶然の一致です。私はあなたがゼロからスタートし、foldr
が動作するようになっているかを見るべきだと思います。
ユアーズ壊れています。単一の数値結果に終わるしない何かでそれを試してみてください。
eg: listFoldr (++) "a" ["b", "c", "d"]
あなたは間違った方向に処理しています。
リスト[x1, x2, ..., xk]
で、あなたのlistFoldr
のを計算
f xk (... (f x2 (f x1 i)) ...)
foldr
を計算する必要があり、一方
f x1 (f x2 (... (f xk i) ...))
(比較では、foldl
を計算
f (... (f (f i x1) x2) ...) xk
基本的に、listFoldr f = foldl (flip f)
。)
あなたしているテストケースは、残念なことです
3 - (2 - (1 - 4)) = 1 - (2 - (3 - 4))
あなたはこれらのような機能をテストしているときは、式が正しく評価されることを確認することができますので、非可換と非会合(すなわち、引数およびアプリケーションのための問題)であるf
に渡すようにしてください。もちろん、減算が非可換と非結合で、あなただけの不運ました。