简体   繁体   中英

Couldn't match expected type ‘Bool’ with actual type ‘Int’

howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
          | a && b && c >= m = 3
          | a && b >= m = 2
          | b && c >= m = 2
          | a && c >= m = 2
          | a || b || c >= m = 1
          | otherwise = 0
          where m = a + b + c

please why isnt this code running, I'm getting alot of errors i dont understand

You write in your code:

howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
          
          | a && b >= m = 2
          | b && c >= m = 2
          | a && c >= m = 2
          | a || b || c >= m = 1
          | otherwise = 0
          where m = a + b + c

I here put one case in boldface, but the error applies to all of them. You write as a condition a && b && c >= m . For Haskell this means that you write it like a && b && (c >= m) . Now (&&) is an operator that takes two booleans as operands, and calculates the logical and of these two. But the operands are no booleans. c >= m is a boolean, but a and b are no booleans.

So we have to write the condition on all operands like:

howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
          | a  && b  && c >= m = 3
          | a  && b >= m = 2
          | b  && c >= m = 2
          | a  && c >= m = 2
          | a  || b  || c >= m = 1
          | otherwise = 0
          where m = a + b + c

So now we have booleans, and the program will compile, but it is still semantically incorect. The average is the sum of the elements divided by the number of elements . Here the number of elements is 3, so we should divide it by three. Since dividing a number can lead to numerical errors, and would mean we have to work in the floating point world , it is safer to multiply the element with which we compare with three instead, so:

howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c
          |  >= m  &&  >= m  &&  >= m = 3
          |  >= m  &&  >= m = 2
          |  >= m  &&  >= m = 2
          |  >= m  &&  >= m = 2
          |  >= m  ||  >= m  ||  >= m = 1
          | otherwise = 0
          where m = a + b + c
                
                
                

Now it works, but still it is not elegant: it requires five guards to check the number of conditions, and a total of twelve comparisons. This would thus be rather inefficient.

A better idea is probably to convert True to 1 and False to 0 , we can do this with the bool catamorphism function: bool :: a -> a -> Bool -> a . If we construct it like bool 0 1 then we have a function that converts False to 0 , and True to 1 , we can then write it like:



howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c = 
          where m = a + b + c
                

It can further be improved, but I leave this as an exercise.

The && operator has type Bool -> Bool -> Bool . This means that both operands have to be Bool and the result is also a Bool .

So for example, in the expression a && b >= m , the right operand ( b >= m ) is a Bool , but the left operand ( a ) is not - it's an Int .

So that's why you get an error: the left operand needs to be a Bool , too.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM