代码之家  ›  专栏  ›  技术社区  ›  Paige Ruten

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

  •  1
  • Paige Ruten  · 技术社区  · 15 年前

    我在做练习 YAHT's Recursive Datatype 然后发现写了 listFoldr 功能有点挑战性(主要是因为我不太了解 foldl foldr 起初)。当我终于意识到 福尔德尔 函数成功了,我决定只需简单地交换函数参数就可以更改 listFoldl 函数到 利斯福尔德 功能:

    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
    

    但是 solution 给我的练习和我的练习大不相同。他们 利斯福德 和我的完全一样,但是看看他们 利斯福尔德 :

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

    哪种解决方案更好,是我的还是他们的?其中一个错误吗?(在我的测试中,结果完全相同…)

    4 回复  |  直到 13 年前
        1
  •  4
  •   Brian    15 年前

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

    您应该能够用一个“订单很重要”的例子来演示这一点。例如,

    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
  •  5
  •   newacct    15 年前

    你的解决方案绝对不正确。您已经简单地实现了 foldl 其中函数 f 以相反的顺序接受参数。例如,什么是错误的, foldr (:) [] 应该是列表上的标识函数,但您的函数会反转列表。你的功能不正常还有很多其他原因 foldr 像怎样 福尔德尔 在无限列表中工作,而您的列表则不工作。在你的例子中,它们是相同的,这纯粹是巧合,因为 3 - (2 - (1 - 4)) == 1 - (2 - (3 - 4)) . 我认为你应该从头开始,看看 福尔德尔 是应该工作的。

        3
  •  4
  •   OJ.    15 年前

    你的坏了。尝试一些不以单个数字结果结尾的方法。

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

    你的处理方向不对。

        4
  •  2
  •   Charles Duffy    15 年前

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