【问题标题】:Haskell folding nested listsHaskell 折叠嵌套列表
【发布时间】:2012-02-25 12:22:37
【问题描述】:

目前我正在使用 Haskell。我对 Haskell(以及一般的函数式语言)的了解仍然很低,但我正在努力。 真正困扰我的是一个(正如我认为的)简单的任务:折叠嵌套列表,每个深度折叠一次。

fcalc = foldr (\x y -> (foldr (**) 1 x) * (foldr (**) 1 y)) [1.0, 1.0] [[2.0, 3.0], [4.0, 5.0]]

它应该做什么:2^3 * 4^5 其中 ^ 由 lambda'd 内部折叠完成。遗憾的是它不起作用。

Occurs check: cannot construct the infinite type: t0 = [t0]
In the third argument of `foldr', namely `y'

我已经阅读了一些关于给定“无限类型”错误的信息,主要表明变量被用作例如元素,而它是一个列表。这让我认为外部文件夹的第二个参数是问题,但没有成功。 我只是不明白。 :/

【问题讨论】:

  • 好吧,我想知道你是不是走错了路。首先,你打破了我的一条经验法则:你不使用折叠来直接解决问题,而是使用它们来实现一些中间抽象来解决你的问题。其次,我想知道列表和嵌套列表是否真的是您尝试做的正确数据结构;我感觉您正在处理一个由某种抽象语法树更好地服务的问题区域。

标签: haskell


【解决方案1】:

您的问题是您试图在折叠内的累加器上进行a^b 计算,同时也在每个元素上进行计算。你真正想要的是类似

fcalc = foldr (\x y -> (foldr (**) 1 x) * y) 1 [[1.0, 1.0], [2.0, 3.0], [4.0, 5.0]]

请记住,foldr 的每个步骤的输出都作为下一步的第二个参数插入(例如,本例中的 y 变量)。由于您的 foldr 步骤返回一个数字,因此 y 变量已经是一个数字,因此您不能折叠它。

【讨论】:

  • 天哪,我怎么会以这种错误的方式思考...非常感谢您纠正我对折叠的理解。
【解决方案2】:

不是您问题的答案,而是解决您问题的另一种方法:

haskell> sum $ map ((**) <$> (!! 0) <*> (!! 1)) xs
1032.0

或者,如果您对 pointfree 不满意:

haskell> sum $ map (\x -> let (a:b:_) = x in a ** b) xs
1032.0

【讨论】:

  • 如果您想对只查看前两个元素的事实进行编码,您不妨改用元组。
  • 当然,但前提是您在编译时知道它将是一个元组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 2015-11-14
  • 2015-06-16
相关资源
最近更新 更多