Bao Long Ngo
Bao Long Ngo

Reputation: 77

Divide Int to Int in Haskell

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

Answers (1)

daniel gratzer
daniel gratzer

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

Related Questions