我正在做YAHT的递归数据类型部分的练习,并发现写作listFoldr
函数有点具有挑战性(主要是因为我一开始并没有真正理解 foldl
和 foldr
之间的区别)。 当我最终意识到 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...)
发布评论
评论(4)
你的解决方案肯定是不正确的。 您只需实现一个
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 functionf
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 notfoldr
, like howfoldr
works on infinite lists and yours does not. It is a pure coincidence that they are the same in your example, because3 - (2 - (1 - 4)) == 1 - (2 - (3 - 4))
. I think you should start from scratch and look at howfoldr
is supposed to work.我认为你正在以“相反的顺序”处理元素,所以你的方法是不正确的。
您应该能够通过“顺序很重要”的示例来证明这一点。 例如,类似
where 'f' 是一个函数,类似于
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
where 'f' is a function along the lines of
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".)
你的坏了。 尝试一下最终不会得到单一数字结果的东西。
您的处理方向错误。
Yours is broken. Try it with something that doesn't end up with a single numeric result.
You're processing in the wrong direction.
在列表
[x1, x2, ..., xk]
上,您的listFoldr
进行计算,而
foldr
应该进行计算(相比之下,
Foldl
本质上是计算
listFoldr f = Foldl (flip f)
。)您的测试用例很不幸,因为
当您测试此类函数时,请务必传入
f
是非交换性和非关联性的(即,参数和应用程序顺序很重要),因此您可以确保表达式的计算正确。 当然,减法是非交换性和非结合性的,你只是运气不好。On a list
[x1, x2, ..., xk]
, yourlistFoldr
computeswhereas
foldr
should compute(In comparison,
foldl
computesEssentially,
listFoldr f = foldl (flip f)
.)You're test case is unfortunate, because
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.