
sorry, forgot to send this to the list: Another way to do it is to use accumulating lists. As a simple example, let's consider:
myf p l = reverse (filter p l)
(myf Char.isUpper "Hello Cruel World" ==> "WCH") that is, it returns elements of a list which match the predicate in reverse order. we could write this very slowly using explicit recursion as:
myf2 p [] = [] myf2 p (x:xs) | p x = myf2 p xs ++ [x] | otherwise = myf2 p xs
but traversing the recusive list is very slow. we might induce tail recursion in something like:
myf3 p l = myf3' l [] where myf3' [] acc = acc myf3' (x:xs) acc = myf3' xs (x:acc)
Now, the accumulator 'acc' holds the value we're going to return at the end. So this is pretty much what you want. Now, suppose we're just doing filter without the reversing, but we still want it to be tail recursive. We might think we have to write:
myf4 p l = reverse (myf3' l [])
(where myf3' is as before) this is not so. We can have fun with function composition. What we do is change the accumulator from a list to a function from a list to a list.
myf4 p l = myf4' l id where myf4' [] acc = acc [] myf4' (x:xs) acc | p x = myf4' xs (\l -> acc (x:l)) | otherwise = myf4' xs acc
here, we start out the accumulator as the identity function. to add an element to it, we make a function which takes the old list, adds 'x' to the front and then applies the accumulator. in the base case, we simply apply the empty list to the accumulator function. the second-to-last line can be rewritten a bit more conveniently as:
| p x = myf4' xs (acc . (x:))
the neat thing about this is that you can easily change the way the list goes. as it is, we have filter, but if we flip the order for (.), as in:
| p x = myf4' xs ((x:) . acc)
then we get (reverse . filter). HTH - Hal -- Hal Daume III | hdaume@isi.edu "Arrest this man, he talks in maths." | www.isi.edu/~hdaume
-----Original Message----- From: haskell-cafe-admin@haskell.org [mailto:haskell-cafe-admin@haskell.org] On Behalf Of Mark Carroll Sent: Saturday, June 21, 2003 5:39 AM To: haskell-cafe@haskell.org Subject: Assembling lists start-to-end
I am assembling a list from start to end. I can add elements to the end with "previous ++ [current]" or I can add them with "current : previous" and reverse it when I'm done. Or, maybe I should use some other data structure. (I don't know the length in advance.) Any thoughts?
-- Mark
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (1)
-
Hal Daume