Конкатенация опций фильтра Haskell - PullRequest
2 голосов
/ 30 апреля 2011
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 ]

6 голосов
/ 30 апреля 2011

Запись

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

на самом деле является ошибкой типа (причина, по которой это приводит к ошибке разбора, возможно, вы использовали / = в качестве префикса - но это оператор инфикса).Вы не можете комбинировать функции с (&&), так как это оператор на логических значениях (не на функциях).

На самом деле этот код должен читать:

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

3 голосов
/ 30 апреля 2011

Замените ваш фильтр на понимание списка.

[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]

...