【问题标题】:Using a Function Like foldl Recursively递归使用类似 foldl 的函数
【发布时间】:2015-01-17 21:15:21
【问题描述】:

作为一个练习,我正在尝试编写一个行为方式与 foldl 函数相同的函数,并且我也在尝试使用递归。

我的函数将被调用,“leftFolder”,签名看起来像一个 foldl 函数: leftFolder :: (a -> b -> a) -> a -> [b] -> a

我有点不知道该怎么做,但这是我尝试过的:

leftFolder :: (a -> b -> a) -> a -> [b] -> a
leftFolder [] = []
leftFolder (x:xs) = x (++) (leftFolder xs)

在我看来,这是有道理的。我是说如果列表为空,则返回一个空列表。如果不是,则取列表的头部,然后继续将其附加到尾部。

【问题讨论】:

  • ...当你尝试这个时会发生什么? (我怀疑我可以猜测,但您应该将其添加到您的问题中!)
  • "如果列表为空,则返回一个空列表。"但我不想要一个列表,我想选择一个a
  • 回想一下foldl (+) 2 [3,4,5] = ((2+3)+4)+5。你的leftFolder 应该接受多少个参数?

标签: haskell


【解决方案1】:

您的代码存在很多问题。例如:

  • 你是模式匹配作为第一个参数[],而第一个参数应该是一个函数
  • 您只使用了 1 个参数,而不是您需要的 3 个参数
  • x (++) ... 没有意义;你可能打算使用x:...
  • 在第一个模式匹配中,您将返回一个列表,而您的函数的返回类型不一定是列表

我相信您正在寻找的是:

leftFolder :: (a -> b -> a) -> a -> [b] -> a
leftFolder _ c [] = c
leftFolder fn c (x:xs) = leftFolder fn (fn c x) xs

Live demo

即:如果列表为空,则返回第二个位置的累加值。否则,我们计算新的累加值 (fn c x),然后将其作为第二个参数传递给我们的函数,同时转发 fn 并传递列表的其余部分。

【讨论】:

  • 我想在这里理解你的代码。所以你说我们有这个 leftFolder 函数,我们将通过它传递 3 个参数。 “_”表示我们不关心该参数是什么,然后第二个 c 参数表示累加器的起点。 “[]”表示正在传递的空列表。我需要帮助理解第三行。您是说我们将传递一个函数参数(fn 表示 (+) 之类的东西)和一个累加器变量 c,以及一个带有头部和尾部的列表。我需要帮助了解“leftFolder fn (fn c x) xs”发生了什么
  • leftFolder fn (fn c x) xs 表示将leftFolder 函数递归应用于以下参数:1) 相同的fn 函数2) 通过将fn 应用于原始累加器c 创建的新累加器和列表的头部x,3) 列表的尾部xs(头部元素已处理,从左到右)恕我直言,在这种情况下,leftFolder fn (fn c x) xs 更容易理解
猜你喜欢
  • 1970-01-01
  • 2019-12-06
  • 2014-02-13
  • 2018-07-01
  • 2022-08-10
  • 1970-01-01
  • 1970-01-01
  • 2019-05-29
  • 1970-01-01
相关资源
最近更新 更多