开发者

Haskell filter option concatenation

exchangeSymbols "a§ b$ c. 1. 2. 3/" = filter (Char.isAlphaNum) (replaceStr str " " "_")

The code above is supposed to first replace all "spaces" with "_", then filter the String according to Char.isAlphaNum. Unfortunately the Char.isAlphaNum part absorbs the already exchanged "_", which isn't my intention and i want to hold the "_". So, i thought it would be nice just add an exception to the filter which goes like:

exchangeSymbols "a§ b$ c. 1. 2. 3/" = filter (Char.isAlphaNum && /='_'开发者_运维知识库) (replaceStr str " " "_")

You see the added && not /='_'. It produces a parse error, obviously it is not so easily possible to concatenate filter options, but is there a smart workaround ? I thought about wrapping the filter function, like a 1000 times or so with each recursion adding a new filter test (/='!'),(/='§') and so on without adding the (/='_'). However it doesn't seem to be a handy solution.


Writing

... filter (Char.isAlphaNum && /='_') ...

is actually a type error (the reason why it yields a parse error is maybe that you used /= as prefix - but its an infix operator). You cannot combine functions with (&&) since its an operator on booleans (not on functions).

Acutally this code snipped should read:

... filter (\c -> Char.isAlphaNum c && c /= '_') ...


Replace your filter with a list comprehension.

[x | x <- replaceStr str " " "_", x /= '_', Char.isAplhaNum x]

Naturally, you probably want to have multiple exceptions. So define a helper function:

notIn :: (Eq a) => [a] -> a -> Bool
notIn [] _ = True
notIn x:xs y = if x == y
                  then False
                  else notIn xs

EDIT: Apparently you can use notElem :: (Eq a) => a -> [a] -> Bool instead. Leaving above code for educational purposes.

And use that in your list comprehension:

[x | x <- replaceStr str " " "_", notElem x "chars to reject", Char.isAlphaNum x]

Untested, as haskell isn't installed on this machine. Bonus points if you are doing a map after the filter, since you can then put that in the list comprehension.

Edit 2: Try this instead, I followed in your footsteps instead of thinking it out myself:

[x | x <- replaceStr str " " "_", Char.isAlphaNum x || x == ' ']
[x | x <- replaceStr str " " "_", Char.isAlphaNum x || x `elem` "chars to accept"]

At this point the list comprehension doesn't help much. The only reason I did change it was because I you requested an &&, for which using a list comprehension is great.

Since it seems that you don't quite understand the principle of the list comprehension, its basically applying a bunch of filters and then a map with more than one source, for example:

[(x, y, x + y) | x <- [1, 2, 3, 4, 5], y <- [2, 4], x > y]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜