Haskell “foldl”的实际使用`
今天,当我在编写一个小脚本时,我使用了Haskell “foldl”的实际使用`,haskell,fold,foldleft,Haskell,Fold,Foldleft,今天,当我在编写一个小脚本时,我使用了foldl而不是foldl'。我得到了堆栈溢出,所以我导入了Data.List(foldl'),并对此感到满意。这是我使用foldl的默认工作流。当惰性版本需要评估时,只需使用foldl' Real World Haskell说,在大多数情况下,我们应该使用foldl'而不是foldl。说 通常在foldr和foldl'之间进行选择 但是,如果组合函数在其第一个参数中是惰性的,foldl可能会愉快地返回一个结果,其中foldl'遇到异常 举个例子: (?)
foldl
而不是foldl'
。我得到了堆栈溢出
,所以我导入了Data.List(foldl')
,并对此感到满意。这是我使用foldl
的默认工作流。当惰性版本需要评估时,只需使用foldl'
Real World Haskell
说,在大多数情况下,我们应该使用foldl'
而不是foldl
。说
通常在foldr
和foldl'
之间进行选择
但是,如果组合函数在其第一个参数中是惰性的,foldl
可能会愉快地返回一个结果,其中foldl'
遇到异常
举个例子:
(?) :: 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
的例子?我的意思是,当我们不能用foldl'
替换foldl
时
另外,我知道,很难定义“实用”一词,但我希望你们能理解我的意思
p.p.S.我理解,为什么haskell默认使用lazyfoldl
。我不要求任何人移动这座山,并将严格版本作为默认版本。我只是对独家使用foldl
函数的示例非常感兴趣:)
p.p.p.S.好吧,欢迎大家使用foldl
我可以想到一个(尽管这可能是只有通过优化编译器才能产生好的代码):
它在foldl'
中没有正确的行为:
> foldl (\_ x -> x) (error "emptyList") [error "foo", "last"]
"last"
> foldl' (\_ x -> x) (error "emptyList") [error "foo", "last"]
"*** Exception: foo
下面是一个更实际的示例,使用经典的naive Fibonacci实现来模拟昂贵的计算:
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
在这里,懒惰版本和严格版本在运行时性能上有着巨大的差异,懒惰版本以压倒性优势胜出。当然,您的数字可能因计算机而异,但您肯定会注意到执行速度的不同。foldl'
强制执行每个计算,而foldl
则不执行。这在以下方面也很有用
> foldl f maxBound $ map length [repeat 1, repeat 1, replicate 10 1]
10
与
fib
示例不同,此计算技术上涉及底部,因为length$repeat 1
永远不会完成其计算。通过使f
的两个参数都不严格(正如foldl'
所做的那样),我们实际上有了一个停止的程序,而不是一个永远不会停止的程序。除了避免未定义的
,您还可以使用foldl
来避免潜在的昂贵操作。如果折叠函数在成功操作的早期退出,则可以避免由于懒惰而执行昂贵的计算。可能有更清晰的方法来编写它(我想到了monoids),但是折叠可以很好地用于编译器优化。但是无法想象这样一个函数的好例子。好吧,这看起来真的像?0=0
。但无论如何,谢谢你再举一个例子。你用reverse
再加上foldr
不是更好吗?这样,您也不必处理整个列表。@托梅利斯我不是说这是最好的方法,只是这是一个例子,说明了foldl是一个更好的选择。好吧,谢谢您的回答。现在我有一些使用foldl
的有趣例子:D@TomEllisreverse
处理整个列表。@JeremyList这是真的。我不记得我在想什么了!
> -- 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 f maxBound $ map length [repeat 1, repeat 1, replicate 10 1]
10