[Haskell-beginners] A better way to "integrate"

Christopher Allen cma at bitemyapp.com
Wed May 21 20:12:35 UTC 2014


> Actually I wonder why we don't have both Num and  Group, Ring, Field,
etc...

There are mathy preludes if that's what you're into.


On Wed, May 21, 2014 at 3:03 PM, Giacomo Tesio <giacomo at tesio.it> wrote:

> Actually I wonder why we don't have both Num and  Group, Ring, Field,
> etc...
>
> With GeneralizedNewtypeDeriving it would be awesome!
>
> Giacomo
>
>
> On Wed, May 21, 2014 at 7:01 PM, David Thomas <davidleothomas at gmail.com>wrote:
>
>> Yes, it "should" - in that it would be more expressive and allow types
>> to catch more errors.  The current situation trades that away for
>> reduced complexity.  Make whatever judgement call you want regarding
>> whether that was appropriate.
>>
>> On Wed, May 21, 2014 at 9:57 AM, Dimitri DeFigueiredo
>> <defigueiredo at ucdavis.edu> wrote:
>> > Thanks, the realization that price, cost and volume are different
>> quantities
>> > is exactly what led me to play around with the Units library.
>> >
>> > I have a problem with Num. Shouldn't it be broken up into the
>> fundamentals
>> > of abstract algebra: Group, Ring, Field, etc? Just like is done for
>> > Functors,
>> > Applicative Functors, Monads, etc. It would avoid having the
>> > typechecker allow me to multiply a Meter by Meter to get another Meter
>> > (instead of the correct unit Meter^2).
>> >
>> > Cheers,
>> >
>> > Dimitri
>> >
>> >
>> > Em 21/05/14 10:39, Brent Yorgey escreveu:
>> >
>> >> Others have given examples of implementing this using a fold.  I'd
>> >> like to point out something else: by representing all these prices and
>> >> volumes etc. as a bare numeric type, you are simply asking for
>> >> trouble!  The reason is that it allows many nonsensical operations.
>> >> For example, you could add a price and a volume.  Adding a price and a
>> >> volume makes no sense, but if they are the same type then the compiler
>> >> cannot help you catch such a silly mistake.
>> >>
>> >> I would do something like this:
>> >>
>> >>    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
>> >>
>> >>    newtype Price = Price Double
>> >>    -- you could also do  newtype Price a = Price a  if you want the
>> >>    -- flexibility to be able to use any numeric type, though it's
>> >>    probably not necessary.
>> >>
>> >>    newtype Volume = Volume Double
>> >>      deriving Num
>> >>    newtype Cost = Cost Double
>> >>      deriving Num
>> >>
>> >> Notice I made a third type Cost, which is the result of multiplying a
>> >> Price by a Volume.  If I understand the domain correctly, multiplying
>> >> a Price by a Volume does not give you another Price (for example,
>> >> would it make sense to multiply a Price by a Volume, and then take the
>> >> result and multiply it by another Volume?).  A Price represents the
>> >> value of a single share or unit of currency, whereas a Cost just
>> >> represents some arbitrary amount of money.
>> >>
>> >> Now, what sorts of operations can one do on these types?  Notice I put
>> >> "deriving Num" after Volume and Cost, which means that two Volumes can
>> >> be added or subtracted to give another Volume, and similarly for Cost
>> >> (unfortunately, it means they can also be multiplied, which is
>> >> probably not sensible, but that's more a failing of the Num class
>> >> which is not granular enough).  We also should implement
>> >>
>> >>    (.*) :: Price -> Volume -> Cost
>> >>    Price p .* Volume v = Cost (p * v)
>> >>
>> >> And now you can implement essentially any of the suggested solutions,
>> >> but with more descriptive types like
>> >>
>> >>    aggregate :: [(Price, Volume)] -> [(Cost, Volume)]
>> >>
>> >> and using (.*) in the key place instead of (*).  And now the type
>> >> checker will make sure you don't do silly things like add a Price and
>> >> a Volume, or multiply a Cost by a Price!  Hooray!
>> >>
>> >> -Brent
>> >>
>> >> On Tue, May 20, 2014 at 08:12:59PM -0600, Dimitri DeFigueiredo 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 at haskell.org
>> >>> http://www.haskell.org/mailman/listinfo/beginners
>> >>
>> >> _______________________________________________
>> >> Beginners mailing list
>> >> Beginners at haskell.org
>> >> http://www.haskell.org/mailman/listinfo/beginners
>> >
>> >
>> > _______________________________________________
>> > Beginners mailing list
>> > Beginners at haskell.org
>> > http://www.haskell.org/mailman/listinfo/beginners
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20140521/a16aef4f/attachment-0001.html>


More information about the Beginners mailing list