我正在从YAHT's Recursive Datatype部分进行练习,发现编写listFoldr
函数有点挑战(主要是因为我并不真正理解foldl
和{{1}之间的区别}} 首先)。当我最终确切地意识到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
但是练习的solution与我的大不相同。他们的Main> foldr (-) 4 [1, 2, 3]
-2
Main> listFoldr (-) 4 [1, 2, 3]
-2
与我的完全相同,但请查看他们的listFoldl
:
listFoldr
哪种解决方案更好,我的还是他们的?其中一个是不正确的? (在我的测试中,他们都得到了完全相同的结果......)
答案 0 :(得分:5)
您的解决方案绝对不正确。您只需实现foldl
,其中函数f
以相反的顺序接受参数。例如,出现了什么问题,foldr (:) []
应该是列表上的识别函数,但是您的函数会反转列表。您的函数不是foldr
的原因还有很多其他原因,例如foldr
如何在无限列表中工作而您的函数不在。{1}}。在你的例子中它们是相同的,这是纯粹的巧合,因为3 - (2 - (1 - 4)) == 1 - (2 - (3 - 4))
。我认为你应该从头开始看看foldr
应该如何运作。
答案 1 :(得分:4)
我认为你正在以“相反的顺序”处理元素,因此你的不对。
您应该能够通过“订单重要”的示例来证明这一点。例如,像
listfoldr f "" ["a", "b", "c"]
其中'f'是
行的函数f s1 s2 = "now processing f(" @ s1 @ "," @ s2 @ ")\n"
其中'@'是一个字符串附加运算符(我忘记它在Haskell中的含义)。关键在于“检测”函数,以便您可以看到使用各种参数调用它的顺序。
(请注意,这并未出现在您的示例中,因为数学“4-1-2-3”产生与“4-3-2-1”相同的答案。)
答案 2 :(得分:4)
你的坏了。尝试使用不会产生单个数字结果的东西。
eg: listFoldr (++) "a" ["b", "c", "d"]
你的处理方向错误。
答案 3 :(得分:2)
在列表[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
(即参数和应用程序顺序问题),这样您就可以确定表达式已被评估正确。当然,减法是非交换性和非关联性的,你只是运气不好。