Hi everyone,<br><br>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.<br>
<br>Any help is greatly appreciated. Thank you,<br>Michael<br><br>------------------------------<div id=":8w" class="ArwC7c ckChnd">----<br><br>{-# LANGUAGE MultiParamTypeClasses #-}<br><br>import Prelude hiding (sum, product)<br>
<br>class Addable a where<br>
add :: a -> a -> a<br> zero :: a<br><br> sum :: [a] -> a<br> sum = foldr add zero<br><br>class Multiplicable a b c where<br> mult :: a -> b -> c<br><br> product :: [a] -> [b] -> [c]<br>
product x y = map (\(x1, y1) -> x1 `mult` y1) $ zip x y<br><br>sumProduct :: (Addable c, Multiplicable a b c) => [a] -> [b] -> c<br>sumProduct x y = sum $ product x y<br><br>weightedAverage x y = (sumProduct y x) `divide` (sum y)<br>
<br>class Dividable a b c where<br> divide :: c -> a -> b<br><br>newtype MilesPerGallon = MilesPerGallon Double deriving Show<br>newtype Gallon = Gallon Double deriving Show<br>newtype Mile = Mile Double deriving Show<br>
<br>instance Addable Gallon where<br> add (Gallon x) (Gallon y) = Gallon $ x + y<br> zero = Gallon 0<br><br>instance Addable Mile where<br> add (Mile x) (Mile y) = Mile $ x + y<br> zero = Mile 0<br><br>instance Multiplicable Gallon MilesPerGallon Mile where<br>
mult (Gallon x) (MilesPerGallon y) = Mile $ x * y<br><br>instance Dividable Gallon MilesPerGallon Mile where<br> divide (Mile x) (Gallon y) = MilesPerGallon $ x / y<br><br>milesPerGallon :: [MilesPerGallon]<br>milesPerGallon = map MilesPerGallon [35, 25, 29, 20, 52]<br>
<br>gallons :: [Gallon]<br>gallons = map Gallon [500, 190, 240, 100, 600]<br><br>totalGallons :: Gallon<br>totalGallons = sum gallons<br><br>totalMiles :: Mile<br>totalMiles = sumProduct gallons milesPerGallon<br><br>totalMilesPerGallon :: MilesPerGallon<br>
totalMilesPerGallon = totalMiles `divide` totalGallons<br>-- I would like some way to get the following line to replace the previous<br>--totalMilesPerGallon = weightedAverage milesPerGallon gallons<br><br>main = do<br> putStrLn $ "Total gallons of gas used: " ++ show totalGallons<br>
putStrLn $ "Total miles traveled: " ++ show totalMiles<br> putStrLn $ "Average miles per gallon: " ++ show totalMilesPerGallon</div>