fold 如何对空列表起作用?
How does fold works for empty list?
当我们折叠一个包含一个或多个元素的列表时,如下所示:
foldr (+) 0 [1,2,3]
We get:
foldr (+) 0 (1 : 2 : 3 : [])
foldr (+) 1 + (2 +(3 + 0)) // 6
现在当列表为空时:
foldr (+) 0 []
Result: foldr (+) 0 ([])
由于 (+) 是二元运算符,它需要两个参数才能完成,但这里我们以 (+) 0
结尾。它如何导致 0 而不是抛出部分应用函数的错误。
简答:你得到初始值z
.
如果您给 foldl
或 foldr
一个空列表,那么它 return 是 初始 值。 foldr :: (a -> b -> b) -> b -> t a -> b
工作方式如下:
foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)
因此,由于没有 x1
、...、xn
函数从未应用,z
被 returned。
我们还可以检查 source code:
foldr :: (a -> b -> b) -> b -> [a] -> b
-- foldr _ z [] = z
-- foldr f z (x:xs) = f x (foldr f z xs)
{-# INLINE [0] foldr #-}
-- Inline only in the final stage, after the foldr/cons rule has had a chance
-- Also note that we inline it when it has *two* parameters, which are the
-- ones we are keen about specialising!
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
因此,如果我们给 foldr
一个空列表,那么 go
将立即处理该空列表,并且 return z
初始值。
因此,更简洁的语法(并且效率稍低,如函数注释中所写)是:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
请注意 - 根据 f
的实现 - 可以 foldr
在无限列表上:如果在某个时候 f
只查看初始值,然后return是一个值,那么递归部分可以去掉。
当我们折叠一个包含一个或多个元素的列表时,如下所示:
foldr (+) 0 [1,2,3]
We get:
foldr (+) 0 (1 : 2 : 3 : [])
foldr (+) 1 + (2 +(3 + 0)) // 6
现在当列表为空时:
foldr (+) 0 []
Result: foldr (+) 0 ([])
由于 (+) 是二元运算符,它需要两个参数才能完成,但这里我们以 (+) 0
结尾。它如何导致 0 而不是抛出部分应用函数的错误。
简答:你得到初始值z
.
如果您给 foldl
或 foldr
一个空列表,那么它 return 是 初始 值。 foldr :: (a -> b -> b) -> b -> t a -> b
工作方式如下:
foldr f z [x1, x2, ..., xn] == x1 `f` (x2 `f` ... (xn `f` z)...)
因此,由于没有 x1
、...、xn
函数从未应用,z
被 returned。
我们还可以检查 source code:
foldr :: (a -> b -> b) -> b -> [a] -> b -- foldr _ z [] = z -- foldr f z (x:xs) = f x (foldr f z xs) {-# INLINE [0] foldr #-} -- Inline only in the final stage, after the foldr/cons rule has had a chance -- Also note that we inline it when it has *two* parameters, which are the -- ones we are keen about specialising! foldr k z = go where go [] = z go (y:ys) = y `k` go ys
因此,如果我们给 foldr
一个空列表,那么 go
将立即处理该空列表,并且 return z
初始值。
因此,更简洁的语法(并且效率稍低,如函数注释中所写)是:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr _ z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
请注意 - 根据 f
的实现 - 可以 foldr
在无限列表上:如果在某个时候 f
只查看初始值,然后return是一个值,那么递归部分可以去掉。