5

zipWith 関数には 2 つの厳密なバージョンがあります。

1) 非常に厳密で、リスト l1 と l2 の要素が評価されるため、それらのサンクがすべてのスタック スペースを消費することはありません (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 番目の例の同等のコードで、関数も厳密にならないのはなぜですか?

4

2 に答える 2

15

使用するのはよくある間違いです

x `seq` x

これは正確に同等です

x

優れた説明は、BadStrictnessに関するNeilMitchellの投稿にあります。

于 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 に答える