[Haskell-cafe] Removing alternate items from a list

Markus Läll markus.l2ll at gmail.com
Wed Jun 9 16:48:50 EDT 2010


Forgot the file -- here it is:

module Main where

import Data.Either (rights)
import Data.Function (fix)

test f = putStr $ show $ last $ f $ replicate 10000000 (1 :: Int)

main = test matchPattern4
-- 1. zipNums
-- 2. matchPattern
-- 3. zipBoolCycle
-- 4. iterDrop
-- 5. zipBoolCycle2
-- 6. consume
-- 7. eitherr
-- 8. golf
-- 9. matchPattern2
-- 10. matchPattern3
-- 11. matchPattern4
-- 12. matchPattern5
-- 13. matchPattern10

-- 1. total time  =       13.72 secs   (686 ticks @ 20 ms)
--    total alloc = 1,840,007,000 bytes  (excludes profiling overheads)
zipNums = map snd . filter (odd . fst) . zip [1,2..]

-- 2. total time  =        1.82 secs   (91 ticks @ 20 ms)
--    total alloc = 400,006,752 bytes  (excludes profiling overheads)
matchPattern (x:_:zs) = x : matchPattern zs
matchPattern x = x

-- 3. total time  =        4.46 secs   (223 ticks @ 20 ms)
--    total alloc = 1,040,006,904 bytes  (excludes profiling overhea
zipBoolCycle xs = map fst . filter snd $ zip xs (cycle [False, True])

-- 4 total time  =        5.20 secs   (260 ticks @ 20 ms)
--   total alloc = 940,006,916 bytes  (excludes profiling overheads)
iterDrop = map head . takeWhile (not . null) . iterate (drop 2) . drop 1


-- 5 total time  =        3.68 secs   (184 ticks @ 20 ms)
--   total alloc = 820,006,872 bytes  (excludes profiling overheads)
zipBoolCycle2 x = [y | (True, y) <- zip (cycle [False, True]) x]


-- 6. total time  =        2.46 secs   (123 ticks @ 20 ms)
--    total alloc = 420,006,860 bytes  (excludes profiling overheads)
data Consume = Take | Skip
consumeBy :: [Consume] -> [a] -> [a]
consumeBy [] _ = []
consumeBy _ [] = []
consumeBy (tOrS:takesAndSkips) (x:xs) =
   case tOrS of Take -> x : consumeBy takesAndSkips xs
                Skip -> consumeBy takesAndSkips xs
consume = consumeBy $ cycle [Take, Skip]


-- 7. total time  =        4.10 secs   (205 ticks @ 20 ms)
--    total alloc = 1,000,006,884 bytes  (excludes profiling overheads)
eitherr = rights . zipWith ($) (cycle [Left,Right])


-- 8. total time  =        2.08 secs   (104 ticks @ 20 ms)
--    total alloc = 420,006,784 bytes  (excludes profiling overheads)
golf = (fix $ \f xs -> case xs of { (x:_: xs) -> x : f xs; _ -> [] })


-- 9. total time  =        1.68 secs   (84 ticks @ 20 ms)
--    total alloc = 370,006,752 bytes  (excludes profiling overheads)
matchPattern2 (a:_:c:_:rest)  = a : c : matchPattern2 rest
matchPattern2 (a:_:rest)      = a : rest
matchPattern2 (rest)          = rest

-- 10. total time  =        1.58 secs   (79 ticks @ 20 ms)
--     total alloc = 360,006,744 bytes  (excludes profiling overheads)
matchPattern3 (a:_:c:_:e:_: rest) = a : c : e : matchPattern3 rest
matchPattern3 (a:_:c:_:rest)      = a : c : rest
matchPattern3 (a:_:rest)          = a : rest
matchPattern3 (rest)              = rest

-- 11. total time  =        1.56 secs   (78 ticks @ 20 ms)
--     total alloc = 355,006,752 bytes  (excludes profiling overheads)
matchPattern4 (a:_:c:_:e:_:g:_:rest) = a : c : e : g : matchPattern4 rest
matchPattern4 (a:_:c:_:e:_: rest)    = a : c : e : rest
matchPattern4 (a:_:c:_:rest)         = a : c : rest
matchPattern4 (a:_:rest)             = a : rest
matchPattern4 (rest)                 = rest

-- 12. total time  =        1.52 secs   (76 ticks @ 20 ms)
--     total alloc = 352,006,752 bytes  (excludes profiling overheads)
matchPattern5 (a:_:c:_:e:_:g:_:i:_:rest) = a : c : e : g : i :
matchPattern5 rest
matchPattern5 (a:_:c:_:e:_:g:_:rest)     = a : c : e : g : rest
matchPattern5 (a:_:c:_:e:_: rest)        = a : c : e : rest
matchPattern5 (a:_:c:_:rest)             = a : c : rest
matchPattern5 (a:_:rest)                 = a : rest
matchPattern5 (rest)                     = rest

-- 13. total time  =        1.48 secs   (74 ticks @ 20 ms)
--     total alloc = 346,006,752 bytes  (excludes profiling overheads)
matchPattern10 (a:_:c:_:e:_:g:_:i:_:k:_:m:_:o:_:q:_:s:_:rest) =
a:c:e:g:i:k:m:o:q:s: matchPattern10 rest
matchPattern10 (a:_:c:_:e:_:g:_:i:_:k:_:m:_:o:_:q:_:rest)     =
a:c:e:g:i:k:m:o:q:rest
matchPattern10 (a:_:c:_:e:_:g:_:i:_:k:_:m:_:o:_:rest)         =
a:c:e:g:i:k:m:o:rest
matchPattern10 (a:_:c:_:e:_:g:_:i:_:k:_:m:_:rest)             =
a:c:e:g:i:k:m:rest
matchPattern10 (a:_:c:_:e:_:g:_:i:_:k:_:rest)                 = a:c:e:g:i:k:rest
matchPattern10 (a:_:c:_:e:_:g:_:i:_:rest)                     = a:c:e:g:i:rest
matchPattern10 (a:_:c:_:e:_:g:_:rest)                         = a:c:e:g:rest
matchPattern10 (a:_:c:_:e:_: rest)                            = a:c:e:rest
matchPattern10 (a:_:c:_:rest)                                 = a:c:rest
matchPattern10 (a:_:rest)                                     = a:rest
matchPattern10 (rest)                                         = rest

On Wed, Jun 9, 2010 at 11:47 PM, Markus Läll <markus.l2ll at gmail.com> wrote:
> So out of curiosity i took the definitions given in this thread, and
> tried to run timing-tests.
> Here's what I ran:
>> ghc -prof -auto-all -o Test Test.h
>> Test +RTS -p
> and then looked in the Test.prof file.
>
> All tests I ran from 3 to 10 times (depending on how sure I wanted to
> be), so the  results are not entirely exact. (I copied the "average"
> result to the source-file as comments above every function.)
>
> As the function doing (x:_:rest) pattern-matching was the fastest I
> extended the idea from that to (x1:_:x2: ... x10:_:rest), but skipping
> from 5 to 10, where all steps showed a small increase in performance.
>
> So a question: when increasing the pattern matched, is it somekind of
> way of inlining the matchings, and if so, is there some way of just
> saying that to the compiler how many recursions you want to inline
> together to increase speed?
>
> Any comments? (besides -O2 ;-)  -- I remembered it too late and didn't
> want to restart... At least for the last two functions it showed a
> similar difference in seconds as with no -O2)
>
>
> Markus Läll
>


More information about the Haskell-Cafe mailing list