Haskell:与列表匹配的模式

use*_*032 0 haskell design-patterns function list matching

我正在尝试创建一个列表中的函数,如果其中一个元素为负数,那么该列表中与其正对应元素相等的任何元素都应该更改为0.例如,如果有一个-2在列表中,该列表中的所有2都应更改为0.

任何想法为什么它只适用于某些情况而不适用于其他情况?我不明白为什么会这样,我已经好几次看过了.

changeToZero [] = []
changeToZero [x] = [x]
changeToZero (x:zs:y:ws) | (x < 0) && ((-1)*(x) == y) = x : zs : 0 : changeToZero ws
changeToZero (x:xs) = x : changeToZero xs
Run Code Online (Sandbox Code Playgroud)

*Main> changeToZero [-1,1,-2,2,-3,3]

[-1,1,-2,2,-3,3]

*主要> changeToZero [-2,1,2,3]

[-2,1,0,3]

*主要> changeToZero [-2,1,2,3,2]

[-2,1,0,3,2]

*Main> changeToZero [1,-2,2,2,1]

[1,-2,2,0,1]

ham*_*mar 6

我认为列表理解更清晰,更容易在这里得到.

changeToZero xs = [if x > 0 && (-x) `elem` xs then 0 else x | x <- xs]
Run Code Online (Sandbox Code Playgroud)

如果你需要更高效的东西,你可以构建一组负面元素并检查它而不是使用elem.

import qualified Data.Set as Set

changeToZero' xs = [if (-x) `Set.member` unwanted then 0 else x | x <- xs]
  where unwanted = Set.fromList $ filter (< 0) xs
Run Code Online (Sandbox Code Playgroud)