inits

Donald Bruce Stewart dons at cse.unsw.edu.au
Tue Apr 11 05:55:36 EDT 2006


ross:
> On Mon, Apr 10, 2006 at 06:00:59PM +0100, Chris Kuklewicz wrote:
> > Ross Paterson wrote:
> > > On Mon, Apr 10, 2006 at 03:54:09PM +0100, Chris Kuklewicz wrote:
> > >> If the goal is speed, then this definition is running over 10% faster with ghc
> > >> -O2 on my powerbook for (sum $ map length $ inits [1..10000])
> > >>
> > >> inits' = helper id
> > >>     where helper f [] = (f []):[]
> > >>           helper f (x:xs) = (f []):helper (f.(x:)) xs
> > > 
> > > I rather like
> > > 
> > > 	inits = map ($ []) . scanl (.) id . map (:)
> > 
> > That takes 3 times longer than the helper function definition.
> 
> Sorry, I meant it appeals to my perverse sense of aesthetics.  It is of
> course the de-fused version of helper.
> 
> > > 	inits = map reverse . scanl (flip (:)) []
> > 
> > I would never try "reverse" when looking for performance, but that runs at the
> > same speed as the helper and allocates the same amount of space.
> 
> It's not really surprising: the nested composition built by helper is
> essentially a list, which is traversed by ($ []).  If scanl were defined
> using build it might run a tiny bit faster.

Ah! Looks like a bit like DList code, from a lib by Manuel Chakravarty:

    -- | a difference list is a function that given a list returns the original
    -- contents of the difference list prepended at the given list
    type DList a = [a] -> [a]

    -- | open a list for use as a difference list
    openDL :: [a] -> DList a
    openDL  = (++)

    -- | create a difference list containing no elements
    zeroDL :: DList a
    zeroDL  = id

    -- | create difference list with given single element
    unitDL :: a -> DList a
    unitDL  = (:)

    -- | append a single element at a difference list
    snocDL      :: DList a -> a -> DList a
    snocDL dl x  = \l -> dl (x:l)

    -- | appending difference lists
    joinDL :: DList a -> DList a -> DList a
    joinDL  = (.)

    -- | closing a difference list into a normal list 
    closeDL :: DList a -> [a]
    closeDL  = ($[])

Which I've used on occasion to write faster code when doing lots of appends.

-- Don


More information about the Libraries mailing list