Function 为什么这些褶皱在头部/尾部停止?
我正在阅读learnyouahaskell.com,目前正在调查褶皱。书中有以下例子:Function 为什么这些褶皱在头部/尾部停止?,function,haskell,functional-programming,fold,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) =>
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'
,我都懂
我的理解是,二进制函数应该依次应用于累加器和列表中的每个元素,从而遍历所有列表。为什么这会停在头部(或尾部)
我理解
。
(下划线)的意思是“不管什么”或“我不在乎”,但这怎么会停止浏览所有列表呢?foldr将两个项目组合在一起—当前的“运行总计”类项目和新项目
(\x\ux->x)
接受新项目并丢弃它,保留原始项目,因此忽略所有剩余项目
让我们扩展一下:
foldr1 (\x _ -> x) [1..100000]
= (\x _ -> x) 1 (foldr (\x _ -> x) [2..100000])
= 1
由于不需要(foldr(\x\ux->x)[2..100000])
术语,因此不会对其进行求值(这是活动中的延迟求值,或者更确切地说是不活动),因此运行速度很快
使用
(\\ux->x)
,将获取新项目并忽略旧项目-这种情况一直持续到列表末尾,因此您将获得最后一个元素。它没有避开其他的,只是忘记了所有的,除了最后一个
一个更易于理解的名称(\\ux->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
首先让我们看一下
foldr1
的定义:
foldr1 :: (a -> a -> a) -> [a] -> a
foldr1 f [x] = x
foldr1 f (x : xs) = f x (foldr1 f xs)
然后,考虑函数的调用<代码>头< <代码>,
head' :: [a] -> a
head' = foldr1 (\x _ -> x)
对于列表,例如,[2,3,5]
:
head' [2, 3, 5]
现在,在标题的右侧填充“
将给出
foldr1 (\x _ -> x) [2, 3, 5]
回想一下,[2,3,5]
是(2:3:5:[])
的语法糖。因此,foldr1
定义的第二种情况适用,我们给出
(\x _ -> x) 2 (foldr1 (\x _ -> x) (3 : 5 : [])
现在,减少应用程序会导致2
绑定到x
和foldr1(\x->x)(3:5:[])
绑定到被忽略的参数。左侧是lambda抽象的右侧,其中x
被2
替换:
2
请注意,延迟求值使得被忽略的参数foldr1(\x u->x)(3:5:[])
未被求值,因此,这很有希望回答您的问题,在我们处理完列表的其余部分之前,递归停止。Haskell的延迟求值不会加快帖子中的标题的速度吗foldr1(\x\ux->x)[1..100000000000000]
在GHCi中运行不到一眨眼。