<div dir="ltr"><div>Though I'm late to the party I might as well post what I have.  Anyways yeah foldr/foldl is the answer when you find yourself iterating over a list with an accumulator.<br><br>aggregate :: [(Price,Volume)] -> [(Price, Volume)]<br>
aggregate = reverse . snd . foldl' proc ((0,0),[])<br>  where<br>    proc  ((!totalp,!totalv),sofar) (Price !p,Volume !v) =<br>      let adjustedprice = round (fromIntegral p * v)<br>      in ((adjustedprice+totalp,v+totalv), ((Price $ adjustedprice + totalp, Volume $ v+totalv) : sofar))<br>
<br></div>Just make sure you use foldl' instead of foldl for performance reasons.  And also try to prepend to lists whenever possible and then reverse if you need to.<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Tue, May 20, 2014 at 10:12 PM, Dimitri DeFigueiredo <span dir="ltr"><<a href="mailto:defigueiredo@ucdavis.edu" target="_blank">defigueiredo@ucdavis.edu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Awesome haskellers,<br>
<br>
I am coding up a little function that aggregates "ask orders" in a currency exchange.<br>
Another way to look at it, is that the function takes as input a histogram or fdf (in list format) and outputs the cumulative distribution cdf (also in list format). So we are kind of "integrating" the input list.<br>

<br>
When given a list of asks in order of increasing price, the function returns a list of points in the graph of the total supply curve.<br>
<br>
Here's an example:<br>
<br>
asks:                           returned list:<br>
<br>
[ (Price 42, Volume 0.5),      [ (Price 21,         Volume 0.5),<br>
  (Price 50, Volume  1 ),        (Price 21+50=71,   Volume 1.5),<br>
  (Price 55, Volume 0.2)]        (Price 21+50+11=82,Volume 1.7)]<br>
<br>
the returned list gives us the total supply curve (price = y-axis, quantity/volume = x-axis, so the order is flipped)<br>
<br>
Summarizing<br>
<br>
* We're adding up the volumes. The last volume on the list is the total volume available for sale.<br>
* We calculate the total amount to be paid to buy the current volume (for each item in the list).<br>
<br>
I have written up a simple function to do this:<br>
<br>
aggregate :: Num a => [(a,a)] -> [(a,a)]<br>
aggregate xs = aggregate' 0 0 xs<br>
<br>
aggregate' :: Num a => a -> a -> [(a,a)] -> [(a,a)]<br>
aggregate' _ _ [] = []<br>
aggregate' accX accY ((x,y):ls) = let accX' = accX + x * y<br>
                                      accY' = accY +     y<br>
<br>
                                      in  (accX',accY') : aggregate' accX' accY' ls<br>
<br>
<br>
main = print $ aggregate [(42,0.5),(50,1),(55,0.2)]<br>
<br>
However, this does not look very good to me and it feels like I'm reinventing the wheel.<br>
<br>
Question: Is there a better Haskell way to do this? I'm really anal about making it easy to read.<br>
<br>
Thanks!<br>
<br>
Dimitri<br>
______________________________<u></u>_________________<br>
Beginners mailing list<br>
<a href="mailto:Beginners@haskell.org" target="_blank">Beginners@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/beginners" target="_blank">http://www.haskell.org/<u></u>mailman/listinfo/beginners</a><br>
</blockquote></div><br></div>