exchangeSymbols "a§ b$ c. 1. 2. 3/" = filter (Char.isAlphaNum) (replaceStr str " " "_")
上面的代码应首先用“_
”替换所有“空格”,然后根据Char.isAlphaNum
过滤字符串。不幸的是Char.isAlphaNum
部分吸收了已经交换的“_”,这不是我的意图,我想持有“_
”。所以,我认为只是在过滤器中添加一个例外情况会很好:
exchangeSymbols "a§ b$ c. 1. 2. 3/" = filter (Char.isAlphaNum && /='_') (replaceStr str " " "_")
您会看到添加的&& not /='_'
。它产生一个parse error
,显然连接过滤器选项并不是那么容易,但有一个聪明的解决方法吗?我考虑过包装过滤器功能,比如每次递归1000次左右,添加新的过滤器测试(/='!')
,(/='§')
等,而不添加(/='_')
。但它似乎不是一个方便的解决方案。
答案 0 :(得分:6)
写作
... filter (Char.isAlphaNum && /='_') ...
实际上是一个类型错误(它产生解析错误的原因可能是您使用/ =作为前缀 - 但它是一个中缀运算符)。您不能将函数与(&&)
结合使用,因为它是布尔运算符的运算符(不是函数)。
实际上,这段代码应该是:
... filter (\c -> Char.isAlphaNum c && c /= '_') ...
答案 1 :(得分:3)
用列表推导替换你的过滤器。
[x | x <- replaceStr str " " "_", x /= '_', Char.isAplhaNum x]
当然,您可能希望有多个例外。所以定义一个辅助函数:
notIn :: (Eq a) => [a] -> a -> Bool
notIn [] _ = True
notIn x:xs y = if x == y
then False
else notIn xs
编辑:显然您可以使用notElem :: (Eq a) => a -> [a] -> Bool
代替。留出以上代码用于教育目的。
并在列表理解中使用它:
[x | x <- replaceStr str " " "_", notElem x "chars to reject", Char.isAlphaNum x]
未经测试,因为haskell未安装在此计算机上。如果您在过滤器后执行地图,则可以获得奖励积分,因为您可以将其放入列表推导中。
编辑2:试试这个,我跟着你的脚步而不是自己想出来:
[x | x <- replaceStr str " " "_", Char.isAlphaNum x || x == ' ']
[x | x <- replaceStr str " " "_", Char.isAlphaNum x || x `elem` "chars to accept"]
此时列表理解并没有多大帮助。我改变它的唯一原因是因为我要求&&
,使用列表理解是很好的。
由于您似乎并不完全理解列表理解的原理,因此它基本上应用了一堆过滤器,然后是一个包含多个源的地图,例如:
[(x, y, x + y) | x <- [1, 2, 3, 4, 5], y <- [2, 4], x > y]