haskell - `foldl`的实际使用

标签 haskell fold foldleft

今天,当我在编写一个小脚本时,我使用了 foldl而不是 foldl' .我得到了stack overflow ,所以我导入了Data.List (foldl')并对此感到满意。这是我的默认工作流程 foldl .只需使用 foldl'当懒惰的版本落入评估。
Real World Haskell说我们应该使用 foldl'而不是 foldl在大多数情况下。 Foldr Foldl Foldl'

Usually the choice is between foldr and foldl'.

...

However, if the combining function is lazy in its first argument, foldl may happily return a result where foldl' hits an exception.



和一个给定的例子:
(?) :: Int -> Int -> Int
_ ? 0 = 0
x ? y = x*y

list :: [Int]
list = [2, 3, undefined, 5, 0]

okey = foldl (?) 1 list

boom = foldl' (?) 1 list

好吧,我很抱歉,但这是相当学术的,有趣但学术的例子。所以我问,有没有实际使用 foldl 的例子? ?我的意思是,当我们无法替换 foldlfoldl' .

P.S. 我知道,这个词很难定义 practical ,但我希望你能明白我的意思。

P.P.S. 我明白了,为什么懒惰 foldl在haskell中是默认的。我不要求任何人搬山并默认使用严格的版本。我只是对 foldl 的独占使用示例非常感兴趣功能 :)

P.P.P.S. 好吧,foldl 的任何有趣用法很受欢迎。

最佳答案

这是一个更实际的例子,它使用经典的朴素斐波那契实现来模拟昂贵的计算:

fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)

f :: Int -> Int -> Int
f a b = if b < 1000 then b else min b a

那么如果你有
> -- Turn on statistics for illustrative purposes
> :set +s
> foldl f maxBound $ map fib [30, 20, 15]
987
(0.02 secs, 0 bytes)
> foldl' f maxBound $ map fib [30, 20, 15]
987
(4.54 secs, 409778880 bytes)

在这里,惰性版本和严格版本之间的运行时性能存在巨大差异,惰性版本以压倒性优势胜出。当然,您的数字可能因您的计算机而异,但您肯定会注意到执行速度的差异。 foldl'强制每个计算发生,而 foldl才不是。这对类似的东西也很有用
> foldl f maxBound $ map length [repeat 1, repeat 1, replicate 10 1]
10

不同于 fib例如,此计算在技术上涉及底部,因为 length $ repeat 1永远不会完成它的计算。通过没有两个参数到 f严格一点(正如 foldl' 所做的那样),我们实际上有一个停止的程序与一个永远不会停止的程序。

关于haskell - `foldl`的实际使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25942098/

相关文章:

haskell - 如何实现 mapAccumM?

haskell - 关于 GADT 样式数据类型声明问题的记录语法

jquery - 三折在线小册子作为网站,如何制作动画?

haskell - 折叠无限列表时堆栈溢出?

scala - Spark Scala FoldLeft 在集群中运行时导致 StackOverflow

带列表的 Scala foldLeft

haskell - 为镜头寻找缺失的状态组合器

haskell - 避免显式传递查找表

haskell - 折叠。 foldr 函数组合 - Haskell

scala - 如何在 Scala 中编写高效的 groupBy-size 过滤器,可以近似