Reputation: 77
I want a function that calculates average mark from a given list of marks. This is what I have made so far:
getAverageRate :: [Int]->Int
getAverageRate marks = (fromIntegral (foldr (+) 0 marks))/(fromIntegral (length marks))
What I am trying to do is to get the sum of all marks in the list by using 'foldr' then divide by 'length marks'. Despite I already use 'fromIntegral' this error still appears and I can not find the problem.
No instance for (Fractional Int) arising from a use of `/'
Possible fix: add an instance declaration for (Fractional Int)
In the expression:
(fromIntegral (foldr (+) 0 marks)) / (fromIntegral (length marks))
In an equation for `getAverageRate':
getAverageRate marks
= (fromIntegral (foldr (+) 0 marks))
/ (fromIntegral (length marks))
Upvotes: 4
Views: 8024
Reputation: 53871
The thing is that Int
represents an integer, so it doesn't make sense to be able to divide it since most divisions result in things which aren't integers.
Happily we have div
, which is integer division, so you could do
average :: [Int] -> Int
average [] = error "Can't average an empty list"
average xs = sum xs `div` length xs
If you don't want to use integer division, then we could do something like
average :: [Int] -> Double
average xs = fromIntegral (sum xs) / fromIntegral (length xs)
which just promotes everything to a Double
for division.
Finally you could choose a method for rounding and go with what you have
average xs = round $ fromIntegral (sum xs) / fromIntegral (length xs)
(Friendly neighborhood warning that sum
is evil and uses foldl
instead of foldl'
so be sure to compile with -O2
when using long lists)
Upvotes: 9