[Haskell-beginners] Weighted average
Michael Snoyman
michael at snoyman.com
Mon Nov 3 16:41:26 EST 2008
Hi everyone,
I'm trying to set up some type safe functions for doing weighted averages
and sum of products. The example I give below is to try and calculate the
average miles per gallon for a collections of vehicles. Unfortunately, I am
unable to get my weightedAverage function to work, seemingly due to an
ambiguity for which instance to use. I think that the issue is that my
"class Multiplicable" should only have two parameters, as opposed to the
three it currently has. However, I can't figure out how to get that to work.
Any help is greatly appreciated. Thank you,
Michael
----------------------------------
{-# LANGUAGE MultiParamTypeClasses #-}
import Prelude hiding (sum, product)
class Addable a where
add :: a -> a -> a
zero :: a
sum :: [a] -> a
sum = foldr add zero
class Multiplicable a b c where
mult :: a -> b -> c
product :: [a] -> [b] -> [c]
product x y = map (\(x1, y1) -> x1 `mult` y1) $ zip x y
sumProduct :: (Addable c, Multiplicable a b c) => [a] -> [b] -> c
sumProduct x y = sum $ product x y
weightedAverage x y = (sumProduct y x) `divide` (sum y)
class Dividable a b c where
divide :: c -> a -> b
newtype MilesPerGallon = MilesPerGallon Double deriving Show
newtype Gallon = Gallon Double deriving Show
newtype Mile = Mile Double deriving Show
instance Addable Gallon where
add (Gallon x) (Gallon y) = Gallon $ x + y
zero = Gallon 0
instance Addable Mile where
add (Mile x) (Mile y) = Mile $ x + y
zero = Mile 0
instance Multiplicable Gallon MilesPerGallon Mile where
mult (Gallon x) (MilesPerGallon y) = Mile $ x * y
instance Dividable Gallon MilesPerGallon Mile where
divide (Mile x) (Gallon y) = MilesPerGallon $ x / y
milesPerGallon :: [MilesPerGallon]
milesPerGallon = map MilesPerGallon [35, 25, 29, 20, 52]
gallons :: [Gallon]
gallons = map Gallon [500, 190, 240, 100, 600]
totalGallons :: Gallon
totalGallons = sum gallons
totalMiles :: Mile
totalMiles = sumProduct gallons milesPerGallon
totalMilesPerGallon :: MilesPerGallon
totalMilesPerGallon = totalMiles `divide` totalGallons
-- I would like some way to get the following line to replace the previous
--totalMilesPerGallon = weightedAverage milesPerGallon gallons
main = do
putStrLn $ "Total gallons of gas used: " ++ show totalGallons
putStrLn $ "Total miles traveled: " ++ show totalMiles
putStrLn $ "Average miles per gallon: " ++ show totalMilesPerGallon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20081103/9bf23093/attachment.htm
More information about the Beginners
mailing list