Haskell过滤器选项连接

时间:2011-04-29 20:51:14

标签: parsing haskell filter concatenation

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次左右,添加新的过滤器测试(/='!')(/='§')等,而不添加(/='_')。但它似乎不是一个方便的解决方案。

2 个答案:

答案 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]