function - 为什么这些褶皱停在头/尾?

标签 function haskell functional-programming fold

我正在阅读 learnyouahaskell.com,目前正在研究折叠。书中有这些例子:

maximum' :: (Ord a) => [a] -> a  
maximum' = foldr1 (\x acc -> if x > acc then x else acc)  

reverse' :: [a] -> [a]  
reverse' = foldl (\acc x -> x : acc) []  

product' :: (Num a) => [a] -> a  
product' = foldr1 (*)  

filter' :: (a -> Bool) -> [a] -> [a]  
filter' p = foldr (\x acc -> if p x then x : acc else acc) []  

head' :: [a] -> a  
head' = foldr1 (\x _ -> x)  

last' :: [a] -> a  
last' = foldl1 (\_ x -> x) 

除了head'我都懂和 tail' .

我的理解是二元函数应该依次应用于累加器和列表中的每个元素,从而遍历所有列表。为什么这会停在头部(或尾部)?

我明白 _ (下划线)表示“随便”或“我不在乎”,但这如何停止遍历所有列表?

最佳答案

一个文件夹组合了两个项目——当前的“运行总计”项目和新项目。
(\x _ -> x)获取新项目并丢弃它,保留原始项目,因此所有剩余项目都将被忽略。

让我们扩展它:

foldr1 (\x _ -> x) [1..100000]
= (\x _ -> x) 1 (foldr (\x _ -> x) [2..100000])
= 1

(foldr (\x _ -> x) [2..100000])不需要 term ,它没有被评估(这是在行动中的懒惰评估,或者更确切地说是不作为),所以它运行得很快。

(\_ x -> x) ,新项目被采用,旧项目被忽略——这种情况一直发生到列表的末尾,所以你得到了最后一个元素。它并没有避免其他的,它只是忘记了除了最后一个之外的所有其他的。

一个更易于理解的名称 (\_ x -> x)指的是它忽略它的第一个参数并返回它的第二个参数的事实。我们叫它secondArg .
foldl1 (\_ x -> x) [1..4]
= let secondArg = (\_ x -> x) in foldl secondArg 1 [2..4]
= foldl (1 `secondArg` 2) [3..4] 
= foldl ((1 `secondArg` 2) `secondArg` 3) [4]
= foldl (((1 `secondArg` 2) `secondArg` 3) `secondArg` 4) []
= (((1 `secondArg` 2) `secondArg` 3) `secondArg` 4)
= 4

关于function - 为什么这些褶皱停在头/尾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16678440/

相关文章:

c++ - 交叉熵误差计算

c - C 递归程序输出不准确

c++ - 在其他函数中对结构 vector 和 vector 部分进行排序?

haskell - 使用列表 monad 实现一个数字计数器

functional-programming - 在 OCaml 中实现 Okasaki 的自举堆,为什么不编译?

python - 如何将列表中的一部分数字分组在一起Python

haskell - 递归与折叠效率

haskell - 为什么镜头包含用于 fromEnum/toEnum 的 Iso,而不包含用于显示/读取的 Iso?

javascript - 网络自动化工具

haskell - Haskell 中的舍入到最近函数