【问题标题】:Is this a correct way of writing the Haskell foldr function?这是编写 Haskell foldr 函数的正确方法吗?
【发布时间】:2009-05-16 05:11:57
【问题描述】:

我在做YAHT's Recursive Datatype 部分的练习,发现编写listFoldr 函数有点挑战性(主要是因为我一开始并没有真正理解foldlfoldr 之间的区别)。当我最终意识到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

但是为练习提供的solution 与我的大不相同。他们的listFoldl和我的一模一样,但是看看他们的listFoldr

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

哪种解决方案更好,我的还是他们的?其中之一不正确吗? (在我的测试中,它们都得到了完全相同的结果......)

【问题讨论】:

    标签: haskell fold combinators


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

      其中'f'是一个函数

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

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

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

      【讨论】:

      • 啊,我想我选择了一种糟糕的测试方式。谢谢!
      • 一个简单的测试是listFoldr (:) "" "abc"(正如newacct 提到的,listFoldr (:) [] 是列表的标识函数)
      【解决方案3】:

      你的坏了。尝试使用不会以单个数字结果结尾的东西。

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

      你的处理方向错误。

      【讨论】:

        【解决方案4】:

        [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(即参数和应用程序顺序问题),这样您就可以确保表达式被正确评估。当然,减法是非交换和非关联的,你只是运气不好。

        【讨论】:

          猜你喜欢
          • 2012-05-03
          • 2012-10-02
          • 2014-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-08
          • 2019-06-29
          • 1970-01-01
          相关资源
          最近更新 更多