Home > OS >  Function that returns a weighted average from a list of lists of numbers
Function that returns a weighted average from a list of lists of numbers

Time:11-11

Write the weightedAverage :: [[Int]] -> Double function, that calculates the grades' weighted average.

For example:

weightedAverage [[3], [5]] == 4.0

weightedAverage [[3,3], [5,5]] == 4.0

weightedAverage [[1,5], [5,5]] == 4.0

weightedAverage [[3,3,3,3], [5,5], [5,5]] == 4.0

So far, I managed to write a function that returns the average of a list:

listAverage :: [Int] -> Double
listAverage [] = 0.0
listAverage x = fromIntegral(sum x)/fromIntegral(length x)

I want to implement this in my weightedAverage function using the following code:

weightedAverage [[]] = 0.0
weightedAverage [x] = listAverage x
weightedAverage (x:xs) = (listAverage x   weightedAverage (xs))/fromIntegral length(x:xs)

The problem is that I get an Ambiguous type variable 't0' arising from a use of 'length' error along with a No instance for (Integral (t0 a0 -> Int)) arising from a use of 'fromIntegral' error. I also think that my recursion is not correctly implemented.

CodePudding user response:

The weight of a list is the number of items. It thus means that we can simply concatenate the list of lists and then determine the average, so you can implement this with:

weightedAverage :: [[Int]] -> Double
weightedAverage = listAverage . …

where is a function :: [[a]] -> [a] that converts a list of list of items to a list of these items.

As for the listAverge, it might make more sense to work with two accumulators that keep track of the sum and the length respectively, something like:

listAverage :: [Int] -> Double
listAverage = go (0 :: Integer) (0 :: Word) . map toInteger
  where go !s !n [] = fromRational (s % toInteger n)
        go s n (x:xs) = …
  • Related