​​
Travesals can usually be implemented using folds, since your list is increasing, I would think to use a foldl, this is my attempt:

foldl :: (a -> b -> a) -> a -> [b] -> a
prices = [(42, 0.5), (50, 1), (55, 0.2)]

agg = foldl accum []
  where accum [] (price, volume) = [(price * volume, volume)]
        accum xs (price, volume) =
          let total = last xs
              total_price = fst total
              total_volume = snd total
              cost = price * volume in
              xs ++ [(total_price + cost, total_volume + volume)]

main = print $ agg prices


Best,
Zhi An


On Wed, May 21, 2014 at 10:12 AM, Dimitri DeFigueiredo <defigueiredo@ucdavis.edu> wrote:
Awesome haskellers,

I am coding up a little function that aggregates "ask orders" in a currency exchange.
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.

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.

Here's an example:

asks:                           returned list:

[ (Price 42, Volume 0.5),      [ (Price 21,         Volume 0.5),
  (Price 50, Volume  1 ),        (Price 21+50=71,   Volume 1.5),
  (Price 55, Volume 0.2)]        (Price 21+50+11=82,Volume 1.7)]

the returned list gives us the total supply curve (price = y-axis, quantity/volume = x-axis, so the order is flipped)

Summarizing

* We're adding up the volumes. The last volume on the list is the total volume available for sale.
* We calculate the total amount to be paid to buy the current volume (for each item in the list).

I have written up a simple function to do this:

aggregate :: Num a => [(a,a)] -> [(a,a)]
aggregate xs = aggregate' 0 0 xs

aggregate' :: Num a => a -> a -> [(a,a)] -> [(a,a)]
aggregate' _ _ [] = []
aggregate' accX accY ((x,y):ls) = let accX' = accX + x * y
                                      accY' = accY +     y

                                      in  (accX',accY') : aggregate' accX' accY' ls


main = print $ aggregate [(42,0.5),(50,1),(55,0.2)]

However, this does not look very good to me and it feels like I'm reinventing the wheel.

Question: Is there a better Haskell way to do this? I'm really anal about making it easy to read.

Thanks!

Dimitri
_______________________________________________
Beginners mailing list
Beginners@haskell.org
http://www.haskell.org/mailman/listinfo/beginners