为什么foldr会立即返回?

时间:2016-01-11 09:38:06

标签: haskell

哈斯克尔的新人。

试图找出原因:

foldr (\_ _ -> 1) 2 [1..]

立即返回1

foldl (\_ _ -> 1) 2 [1..]

永远运行。

阅读一些source code,但仍停留在某些#.

帮帮我。 (在Windows GHC 7.10.3上运行测试)

2 个答案:

答案 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

所以无论你的折叠函数是否评估参数,它都会从列表中构建一个组合函数并将初始值传递给它,因此不会以无限列表终止。