哈斯克尔的新人。
试图找出原因:
foldr (\_ _ -> 1) 2 [1..]
立即返回1
:
foldl (\_ _ -> 1) 2 [1..]
永远运行。
阅读一些source code,但仍停留在某些#.
。
帮帮我。 (在Windows GHC 7.10.3上运行测试)
答案 0 :(得分:3)
该来源是Foldable
的默认foldr
实现,它不是列表的实际实现。实际implementation很简单:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
foldr (\_ _ -> 1) 2 [1..]
的结果可以通过替换来理解:
foldr (\_ _ -> 1) 2 [1..]
go [1..]
go (1 : [2..]) -- evaluate [1..]
(\_ _ -> 1) 1 (go [2..]) -- evaluate `go` at (:) case
1 -- evaluate expression
答案 1 :(得分:0)
特别是在GHC中,foldl实际上是由foldr实现的:
foldl :: forall a b. (b -> a -> b) -> b -> [a] -> b
{-# INLINE foldl #-}
foldl k z0 xs =
foldr (\(v::a) (fn::b->b) -> oneShot (\(z::b) -> fn (k z v))) (id :: b -> b) xs z0
所以无论你的折叠函数是否评估参数,它都会从列表中构建一个组合函数并将初始值传递给它,因此不会以无限列表终止。