这是编写 Haskellfoldr 函数的正确方法吗?

发布于 2024-07-20 04:31:19 字数 1038 浏览 5 评论 0 原文

我正在做YAHT的递归数据类型部分的练习,并发现写作listFoldr 函数有点具有挑战性(主要是因为我一开始并没有真正理解 foldlfoldr 之间的区别)。 当我最终意识到 foldr 函数的工作原理时,我决定只需简单交换函数参数即可将我的 listFoldl 函数更改为 < code>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)

哪个解决方案更好,我的还是他们的? 其中之一是错误的吗? (在我的测试中,它们最终得到完全相同的结果......)

I was doing the exercises from YAHT's Recursive Datatype section, and found writing the listFoldr function a bit challenging (mainly because I didn't really understand the difference between foldl and foldr at first). When I finally realized exactly how the foldr function worked, I decided that a simple swap of function arguments would be all that'd be needed to change my listFoldl function to a listFoldr function:

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

This appears to work (I did more tests than this):

Main> foldr (-) 4 [1, 2, 3]
-2
Main> listFoldr (-) 4 [1, 2, 3]
-2

But the solution given for the exercise is much different than mine. Their listFoldl is exactly the same as mine, but look at their listFoldr:

listFoldr f i [] = i
listFoldr f i (x:xs) = f x (listFoldr f i xs)

Which solution is better, mine or theirs? Is one of them incorrect? (In my tests, they both end up with the exact same result...)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

踏雪无痕 2024-07-27 04:31:19

你的解决方案肯定是不正确的。 您只需实现一个 foldl,其中函数 f 以相反的顺序接受参数。 例如,错误的地方是, foldr (:) [] 应该是列表上的识别函数,但您的函数反转了列表。 还有很多其他原因导致您的函数不是 foldr,例如 foldr 如何在无限列表上工作,而您的函数则不然。 它们在您的示例中相同纯属巧合,因为 3 - (2 - (1 - 4)) == 1 - (2 - (3 - 4))。 我认为你应该从头开始,看看 foldr 应该如何工作。

Your solution is definitely incorrect. You have simply implemented a foldl in which the function f takes arguments in the opposite order. For example of what is wrong, foldr (:) [] is supposed to be an identify function on lists, but your function reverses the list. There are lots of other reasons why your function is not foldr, like how foldr works on infinite lists and yours does not. It is a pure coincidence that they are the same in your example, because 3 - (2 - (1 - 4)) == 1 - (2 - (3 - 4)). I think you should start from scratch and look at how foldr is supposed to work.

因为看清所以看轻 2024-07-27 04:31:19

我认为你正在以“相反的顺序”处理元素,所以你的方法是不正确的。

您应该能够通过“顺序很重要”的示例来证明这一点。 例如,类似

listfoldr f "" ["a", "b", "c"]

where 'f' 是一个函数,类似于

f s1 s2 = "now processing f(" @ s1 @ "," @ s2 @ ")\n"

where '@' 是一个字符串追加运算符(我忘记了它在 Haskell 中是什么)。 重点只是“检测”该函数,以便您可以看到使用各种参数调用它的顺序。

(请注意,这没有出现在您的示例中,因为数学“4-1-2-3”产生与“4-3-2-1”相同的答案。)

I think you are processing the elements in the 'opposite order', and so yours is not right.

You should be able to demonstrate this with an example where 'order matters'. For example, something like

listfoldr f "" ["a", "b", "c"]

where 'f' is a function along the lines of

f s1 s2 = "now processing f(" @ s1 @ "," @ s2 @ ")\n"

where '@' is a string-append operator (I forget what it is in Haskell). The point is just to 'instrument' the function so you can see what order it is getting called with the various args.

(Note that this didn't show up in your example because the math "4-1-2-3" yields the same answer as "4-3-2-1".)

甜宝宝 2024-07-27 04:31:19

你的坏了。 尝试一下最终不会得到单一数字结果的东西。

eg: listFoldr (++) "a" ["b", "c", "d"]

您的处理方向错误。

Yours is broken. Try it with something that doesn't end up with a single numeric result.

eg: listFoldr (++) "a" ["b", "c", "d"]

You're processing in the wrong direction.

执笔绘流年 2024-07-27 04:31:19

在列表 [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 是非交换性和非关联性的(即,参数和应用程序顺序很重要),因此您可以确保表达式的计算正确。 当然,减法是非交换性和非结合性的,你只是运气不好。

On a list [x1, x2, ..., xk], your listFoldr computes

 f xk (... (f x2 (f x1 i)) ...)

whereas foldr should compute

 f x1 (f x2 (... (f xk i) ...))

(In comparison, foldl computes

f (... (f (f i x1) x2) ...) xk

Essentially, listFoldr f = foldl (flip f).)

You're test case is unfortunate, because

3 - (2 - (1 - 4)) = 1 - (2  - (3 - 4))

When you are testing functions like these, be sure to pass in an f that is non-commutative and non-associative (i.e., argument and application order matter), so you can be sure the expression is evaluated correctly. Of course, subtraction is non-commutative and non-associative and you just got unlucky.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文