5

zipWith 函数有两个严格版本:

1) 非常严格,列表 l1 和 l2 的元素得到评估,因此它们的 thunk 不会占用所有堆栈空间(Don Stewart 代码)

zipWith' f l1 l2 = [ f e1 e2 | (e1, e2) <- zipWith k l1 l2 ]
            where
                k x y = x `seq` y `seq` (x,y)

2)不是很严格,尝试通过其他方式强制评估。

zipWith'' f l1 l2 = [ f e1 e2 | (e1, e2) <- zip (map (\x -> x `seq` x) l1) (map (\x -> x `seq` x) l2) ]

问题是:为什么使用map的第二个示例中的等效代码不会使函数也严格?

4

2 回答 2

15

这是一个常见的错误使用

x `seq` x

这完全等同于

x

Neil Mitchell 关于 Bad Strictness 的帖子中有一个很好的解释。

于 2011-06-28T09:23:14.913 回答
3

map可以使用此函数来强制列表,而不是重言式:

evl []     = []
evl (x:xs) = x `seq` (x:evl xs)
-- Cannot figure out how to do this with fold.

然后严格zipWith

zipWith''' f xs ys = zipWith f (evl xs) (evl ys)
于 2011-06-28T10:07:02.410 回答