
Am Sonntag, 22. Februar 2009 15:30 schrieb Heinrich Apfelmus:
Daniel Fischer wrote:
Yes, foldr was the wrong choice. make it foldl' (don't forget the prime at the end) and it works for large tables. If the rows are short, it actually is faster (here) than your version, but if the rows are long , e.g.
maxTableColumnWidths (replicate 2000 (replicate 1000 "what?"))
your version is faster than
import Data.List (foldl')
seqList [] = False seqList (head:tail)
| head `seq` False = undefined | otherwise = seqList tail
evalList xs
| seqList xs = undefined | otherwise = xs
zipWithD :: (a -> a -> a) -> [a] -> [a] -> [a] zipWithD f (x:xt) (y:yt) = f x y:zipWithD f xt yt zipWithD _ [] ys = ys zipWithD _ xs [] = xs
maxTableColumnWidths = foldl' ((evalList .) . zipWithD max) [] . map (map length)
Nice! I'd use bang patterns in favor of the now outdated
| x `seq` False = undefined
pattern though.
I would, too, but they're not yet portable, are they? Which implementations other than GHC currently support them? And since seqList was already there, I used that.
Actually, I'd use
import Control.Parallel.Strategies
maxWidths = foldl' (\xs ys -> zipWithD max xs ys `using` rnf) [] . map (map length)
The module quite useful for controlling evaluation, even when no parallelism is involved.
Winner!
Regards, apfelmus
Cheers, Daniel