[Haskell-cafe] Space usage and CSE in Haskell
Melissa O'Neill
oneill at cs.hmc.edu
Fri Jul 27 21:01:02 EDT 2007
Bertram Felgenhauer wrote two wonderful implementations of power_list:
> power_list :: [a] -> [[a]]
> power_list [] = [[]]
> power_list (x:xs) = add_x (assert_first_empty $ power_list xs) x
> where assert_first_empty ~([]:xs) = []:xs
> add_x [] _ = []
> add_x (y:ys) x = y : (x:y) : add_x ys x
>
> It's safe to replace the ~([]:xs) by ~(_:xs) - this should result
> in slightly more efficient code (but I did no timings).
With GHC, it seems to make no observable difference.
> Finally for lovers of oneliners, here's the same code with foldr,
> slightly obscured by using >>= for concatMap:
>
> power_list :: [a] -> [[a]]
> power_list = foldr (\x ~(_:xs) -> []:xs >>= \ys -> [ys, x:ys]) [[]]
I loved how short and sweet this version is, but sadly with GHC it's
noticeably slower than Bertram's first, more directly coded, version
(1.32 seconds vs 0.55 seconds for power_list [1..24]).
The two-line variant below is just over 25% faster than the above
oneliner under GHC, but at 1.04 seconds, it's still bested by the
explicit version:
power_list :: [a] -> [[a]]
power_list [] = [[]]
power_list (x:xs) = [] : tail [y | ps <- power_list xs, y <- [ps,
x:ps]]
Anyway, we're now far from our original topic, but thanks to Bertram,
we can see that power_list can be coded in a way that is memory
efficient, lazy-list friendly, and (relatively) easy to read.
Best Regards,
Melissa.
More information about the Haskell-Cafe
mailing list