无法将预期类型'Bool'与实际类型'Int'匹配

时间:2018-01-23 15:29:36

标签: haskell functional-programming

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

请问为什么这段代码没有运行,我有很多错误,我不明白

2 个答案:

答案 0 :(得分:6)

您在代码中写道:

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

我在这里用粗体表示一个案例,但错误适用于所有这些案例。你写成条件a && b && c >= m。对于Haskell,这意味着您可以像a && b && (c >= m)一样编写它。现在(&&)是一个操作符,它将两个布尔值作为操作数,并计算逻辑和这两个。但操作数不是布尔。 c >= m是布尔值,但ab不是布尔值。

所以我们必须在所有操作数上编写条件,如:

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

所以现在我们有布尔,程序将编译,但它仍然在语义上是incorect。平均值是元素之和除以元素数。元素的数量是3,所以我们应该将它除以3。由于除数可能导致数值误差,并且意味着我们必须在浮点世界中工作,因此将我们与之比较的元素乘以3会更安全,所以:

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

现在它起作用,但它仍然不优雅:它需要五名警卫来检查条件的数量,总共十二次比较。因此这将是相当低效的。

更好的想法可能是将True转换为1False转换为0,我们可以使用bool catamorphism < / em>功能:bool :: a -> a -> Bool -> a。如果我们像bool 0 1那样构建它,那么我们有一个将False转换为0True转换为1的函数,然后我们就可以这样写:< / p>

import Data.Bool(bool)

howManyAboveAverage :: Int -> Int -> Int -> Int
howManyAboveAverage a b c = booltoint (3*a >= m)
                          + booltoint (3*b >= m)
                          + booltoint (3*c >= m)
          where m = a + b + c
                booltoint = bool 0 1

它可以进一步改进,但我把它留作练习。

答案 1 :(得分:3)

&&运算符的类型为Bool -> Bool -> Bool。这意味着两个操作数必须为Bool,结果也为Bool

例如,在表达式a && b >= m中,右操作数(b >= m)是Bool,但左操作数(a)不是 - 它是一个Int

这就是你收到错误的原因:左操作数也必须是Bool