Why doesn't the map affect severity, while zipWith does?

There are two strict versions of the zipWith function:

1) Really strict, the elements of the lists l1 and l2 are evaluated so that their tricks do not eat the whole space of the stack (Don Stewart code)

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

2) Not very strict, try to force the assessment in a different way.

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

Question: why does the equivalent code from the second example using the card not make the function strict?

+5
source share
2 answers

A common mistake is to use

x `seq` x

Which is exactly equivalent

x

An excellent explanation is available in Neil Mitchell's Report on Bad Strictness .

+15
source

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)
+3

All Articles