为什么map不强制严格,而zipWith呢?

时间:2011-06-28 08:59:51

标签: haskell lazy-evaluation strictness

有两个严格的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 的第二个例子中的等效代码不会使函数也严格?

2 个答案:

答案 0 :(得分:15)

使用

是一个常见的错误
x `seq` x

这完全等同于

x

Neil Mitchell's post on Bad Strictness中提供了一个很好的解释。

答案 1 :(得分: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)