avoiding cost of (++)
Janis Voigtlaender
voigt@orchid.inf.tu-dresden.de
Thu, 16 Jan 2003 18:20:17 +0100
Hal Daume III wrote:
>
> I have a function which behaves like map, except instead of applying the
> given function to, say, the element at position 5, it applies it to the
> entire list *without* the element at position 5. An implementation looks
> like:
>
> > mapWithout :: ([a] -> b) -> [a] -> [b]
> > mapWithout f = mapWith' []
> > where mapWith' pre [] = []
> > mapWith' pre (x:xs) = f (pre ++ xs) : mapWith' (x:pre) xs
>
> Unfortunately, this is very slow, due to the overhead of (++).
The following version avoids concatenations:
mapWithout :: ([a] -> b) -> [a] -> [b]
mapWithout f [] = []
mapWithout f (x:xs) = f xs : mapWithout (\ys -> f (x:ys)) xs
but I doubt that you will see much speedup.
> Any way I could speed this up would be great. Note that order doesn't
> matter to 'f', but I do need that the order in which the elements of the
> list are processed be the same as in map.
The problem is that creating the "list of all sublists with one element
dropped" is inherently of quadratic complexity (or so I think...)
Nice puzzle though: how to minimize constant factors?
Cheers, Janis.
--
Janis Voigtlaender
http://wwwtcs.inf.tu-dresden.de/~voigt/
mailto:voigt@tcs.inf.tu-dresden.de