2012-01-04 6 views
3

У меня есть список месяцев и строка. Я хочу проверить, не находится ли какой-либо из месяцев в строке. У меня также есть функция, которая выполняет поиск строки для слова. Должен ли я переписать эту функцию или это возможно с помощью какой-либо формы карты?Как применить карту использования в этом случае?

fullMons = ["january", "febuary", "march", "april", "may", "june", "july", "september", "october", "november", "december"] 

searchStrList :: String -> [String] -> Bool 
searchStrList str strList = elem (map toLower str) $ convertToLower $ words strList 

Как я могу использовать эти функции, чтобы сделать что-то вроде этого:

check :: String -> Bool 
check str = searchStrList "january" || searchStrList "febuary" || ... 

Все еще только учусь Haskell, поэтому любые другие комментарии на мой код ценится. Спасибо

ответ

9

Обратите внимание, что fullMons это не функция, а список, и searchStrList не типа; words принимает одну строку, но вы применяете ее к списку строк.

Я думаю, что вы пытаетесь найти, содержат ли слова строки какие-либо из имен месяцев в fullMons. Давайте попробуем выработать решение шаг за шагом. Первое, что мы хотим сделать, это применить words к нашей строке ввода; это дает нам список строк.

words str :: [String] 

Затем мы хотим, чтобы выяснить, какой-либо из элементов words s, является ли название месяца. Там есть функция any:

any :: (a -> Bool) -> [a] -> Bool 

Таким образом, наше решение должно выглядеть

check str = any ??? (words str) 

и все, что мы должны сделать, это выяснить ???. elem функция позволяет нам проверить, является ли элемент в списке:

elem :: (Eq a) => a -> [a] -> Bool 

В этом случае список должен быть список месяцев, а элемент мы ищем должно быть слово строки. Таким образом, чтобы заполнить пробел:

check :: String -> Bool 
check str = any (\word -> word `elem` fullMons) (words str) 

(Примечание. foo `op` bar просто op foo bar, много операторов предназначены для записи и чтения таким образом)

Мы можем сделать это проще и более идиоматических избавившись от параметра:

check :: String -> Bool 
check = any (\word -> word `elem` fullMons) . words 

Это означает, что мы применяем words ко входу, а затем применить any (\word -> elem word fullMons) к результату words. Вы могли бы упростить это далее:

check :: String -> Bool 
check = any (`elem` fullMons) . words 

(то есть, «делать какие-либо из элементов words нашего входа появляются в fullMons?«)

, но это не обязательно.

Я думаю, что оригинальное решение, которое вы пытались получить в том, чтобы проверить каждое название месяца на всю строку, в свою очередь. Чтобы сделать это, нам просто нужно переворачивать структура управления немного:

check :: String -> Bool 
check str = any (\word -> word `elem` ws) fullMons 
    where ws = words str 

(то есть, "делать какие-либо из элементов fullMons появляются в words str?")

3

Вы можете использовать функцию any, чтобы проверить, является ли предикат истинным для любого члена списка.

Здесь я использовал isInfixOf функцию от Data.List сделать предикат:

check :: String -> Bool 
check str = any (`isInfixOf` str) fullMons 
0
data Month = January | February | March | April | 
      May | June | July | September | October | November | December 
      deriving (Eq, Show) 

months = [March, December, April] 
april = April `elem` months 

Используйте типы, A й оттуда конвертировать из этих типов в строковое представление, как в:

show April 
+1

'Month' должны получить' 'Enum', Ord' и' Bounded', тоже. Затем вы можете получить весь месяц, например. по 'enumFrom January'. – Landei

Смежные вопросы