I'm getting the error " No instance for (Fractional Int) arising from a use of '/' ", from inside a local definition in a function I'm trying to make which determines how many of the (three) given integers are above the average of all of the given integers. So I've created a local definition inside the function to calculate the average so I can then use it for guard checks. I've used the same code in a separate definition (in another file) to calculate the average and it works. I've tried putting the " fromIntegral " function call in different places but it's not working, where am I going wrong?
Here's the code:
howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
| a > average && b > average = 2
| a > average && c > average = 2
| b > average && c > average = 2
| a > average = 1
| b > average = 1
| c > average = 1
| otherwise = 0
where
average = fromIntegral (a + b + c) / 3
The error is being flagged up on the last line.
Thanks.
You're comparing a
(which is an Int
) and average
(which is Fractional a => a
). Since (>) :: a -> a Bool
, GHC presumes that average
is also an Int
, which doesn't work. You either need to change average
to Int
(for example via round
) or a
, b
and c
to Double
or Float
.
You can also compare integers instead. The idea is that x < (a + b + c)/3
is equivalent to 3*x < a + b + c
.
howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
| gti a av && gti b av = 2
| gti a av && gti c av = 2
| gti b av && gti c av = 2
| gti a av = 1
| gti b av = 1
| gti c av = 1
| otherwise = 0
where
av = a + b + c
gti x m = 3*x > m
Here's a cleaner version of the solution you came up with:
howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
| a' > average && b' > average = 2
| a' > average && c' > average = 2
| b' > average && c' > average = 2
| a' > average = 1
| b' > average = 1
| c' > average = 1
| otherwise = 0
where
average = a' + b' + c' / 3
a' = fromIntegral a
b' = fromIntegral b
c' = fromIntegral c
You can simplify this even further to:
howManyAboveAverage a b c = length (filter (> average) [a', b', c'])
where
average = a' + b' + c' / 3
a' = fromIntegral a
b' = fromIntegral b
c' = fromIntegral c
I've managed to resolve this by adding "fromIntegral" in front of any parameter that was compared to the average.
New (working) code:
howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
| fromIntegral a > average && fromIntegral b > average = 2
| fromIntegral a > average && fromIntegral c > average = 2
| fromIntegral b > average && fromIntegral c > average = 2
| fromIntegral a > average = 1
| fromIntegral b > average = 1
| fromIntegral c > average = 1
| otherwise = 0
where
average = fromIntegral (a + b + c) / 3
It looks a bit messy / cumbersome so if anyone has any other (cleaner) suggestions please let me know.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.