Haskell 以左折叠方式构建列表的最有效方法是什么?
在构建列表时,我通常使用右折叠,因为这样可以使用右关联的Haskell 以左折叠方式构建列表的最有效方法是什么?,haskell,functional-programming,fold,Haskell,Functional Programming,Fold,在构建列表时,我通常使用右折叠,因为这样可以使用右关联的:操作符,而不会影响结果列表的顺序。在左图中,我可以使用++,但我知道这将需要在生成列表时重复复制列表,为N元素列表提供O(N^2)操作,这通常是不可接受的 因此,当我必须使用左折叠时(在我的特定情况下,这是因为我使用的是foldlM,生成的一元动作必须按从左到右的顺序执行),除了使用:在折叠中建立列表并反转结果之外,还有什么更好的方法来协调这一点吗?既然您提到了折叠,我的这篇博文很可能深入地回答了您的问题: 底线是:使用差异列表;i、
:
操作符,而不会影响结果列表的顺序。在左图中,我可以使用++
,但我知道这将需要在生成列表时重复复制列表,为N元素列表提供O(N^2)操作,这通常是不可接受的
因此,当我必须使用左折叠时(在我的特定情况下,这是因为我使用的是
foldlM
,生成的一元动作必须按从左到右的顺序执行),除了使用:
在折叠中建立列表并反转结果之外,还有什么更好的方法来协调这一点吗?既然您提到了折叠
,我的这篇博文很可能深入地回答了您的问题:
底线是:使用差异列表;i、 e.在左侧折叠中,累积类型为[a]->[a]
的值,可以使用附加值。(x:)
高效,最后将此函数应用于[]
以获取列表
当我必须使用左折叠时(…因为…产生的一元动作必须按从左到右的顺序执行)
右折叠可以向右倾斜,使其再次回到左侧。例如,您可以打印(即一元动作)每个数字,并使用右折叠从左到右计算列表的部分和:
请注意,输出列表是使用
(a':)
构建的,一元操作是从左到右执行的,即使它是右折叠。在较新版本的数据中。Foldable.foldl
是根据foldr
定义的,以便与其他操作进行融合reverse
应该是其中之一,因此您只需使用reverse$foldl…
就可以得到一个非常高效的版本。至少是我的猜测。不,反向不参与列表融合。差异列表是否比累积一个列表然后反向好?啊,我想你是这么认为的。我很惊讶;我已经看到了反转技术在其他情况下的胜利(稍微)。整个情况有点不令人满意。我希望看到一个安全的IO
交错组合器,它允许IO
惰性地生成值,但不允许惰性计算驱动IO
。有点懒,我同意;“这是一个有洞的表达式,我稍后会补上这个洞”的组合符会很好。但在任何情况下,它都是对某个闭包的可变更改,而运行时/GC总是会对其进行惩罚。
fun :: [Int] -> IO [Int]
fun xs = foldr go (const $ return []) xs 0
where go x f a = let a' = a + x in print x >> (a' :) <$> f a'
\> fun [1..5]
1
2
3
4
5
[1,3,6,10,15]