"Pattern match is redundant" 在列表推导中使用输入列表参数时

"Pattern match is redundant" when using input list argument inside list comprehension

这是我的代码:

example = [1,-4,7,12]

positiveSum :: [Int] -> Int
positiveSum (x) = 0
positiveSum (x:xs) = result
  where 
    result = sum [y+y | y <- xs, y > 0]

main = do
  print (positiveSum example)

当我 运行 它时,我得到:

Main.hs:5:1: warning: [-Woverlapping-patterns]
    Pattern match is redundant
    In an equation for `positiveSum': positiveSum (x : xs) = ...
  |
5 | positiveSum (x:xs) = result
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^...

我不能在列表理解中使用 'xs',我不明白为什么。这是一个参考,我应该可以使用它。为什么它是多余的?

编辑:

答案解决了问题,我正在匹配第一个 (x)。另外,我把自己弄糊涂了,两次应用 sum 。这是正确的代码:

positiveSum :: [Int] -> Int
positiveSum [] = 0
positiveSum xs = result
  where 
    result = sum [x | x <- xs, x > 0]

模式匹配从上到下,所以每次调用 positiveSum returns 0。由于第一个规则的模式是 positiveSum (x) = 0,它匹配 所有 ,因为每个值都可以绑定到 x。通过将该规则设为最后一条,您可以避免此问题:

positiveSum :: [Int] -> Int
positiveSum (x:xs) = result
  where 
    result = sum [y+y | y <- xs, y > 0]
positiveSum (x) = 0

使用此代码,如果参数没有尾部,我们只会回退到 0 情况,从而导致预期的行为。

你似乎认为 positiveSum (x) = 0 只会匹配空列表的情况,但实际上它会匹配任何东西,这使得下一行变得多余,因为它永远不会被尝试。你打算在那里写 positiveSum [] = 0 。另外,请注意你的第二种情况,即使它现在 运行,也会丢弃列表的头部,你可能不是故意的。

你不需要区分空列表和non-empty列表:你可以计算过滤列表的总和:

positiveSum :: [Int] -> Int
positiveSum xs = sum [y | y <- xs, y > 0]

此处 xs 模式与 所有 可能的列表相匹配:空或非空。 y 将枚举 xs 的所有项目,如果 y > 0,我们产生该值。然后我们计算该列表的总和。对于空列表 sum 将 return 0,因此无论 xs 是否为空,并且存在满足 y > 0 谓词的元素,它将 return 一个值。

另一种选择是使用 filter :: (a -> Bool) -> [a] -> [a],从而确定总和:

positiveSum :: [Int] -> Int
positiveSum = sum . <strong>filter (0 <)</strong>