Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 以左折叠方式构建列表的最有效方法是什么?_Haskell_Functional Programming_Fold - Fatal编程技术网

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]