Reputation: 2375
I have a list of months and a string. I want to check to see if any of the months are in the string. I also have a function that takes searches a string for a word. Do I have to rewrite that function or is this possible with some form of map?
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
How can I utilize these functions to do something like this:
check :: String -> Bool
check str = searchStrList "january" || searchStrList "febuary" || ...
Still just learning Haskell, so any other comments on my code is appreciated. Thanks
Upvotes: 3
Views: 133
Reputation: 535
data Month = January | February | March | April |
May | June | July | September | October | November | December
deriving (Eq, Show)
months = [March, December, April]
april = April `elem` months
Use the types, and from there convert from those types to the string representation, as in:
show April
Upvotes: 0
Reputation: 40797
Note that fullMons
isn't a function but a list, and searchStrList
doesn't type; words
takes a single strings, but you apply it to a list of strings.
I guess what you're trying to do is find whether the words of a string contain any of the month names in fullMons
. Let's try and derive a solution step by step. The first thing we want to do is apply words
to our input string; that gets us a list of strings.
words str :: [String]
Then we want to find out whether any of the elements of words s
is a month name. There's a function any
:
any :: (a -> Bool) -> [a] -> Bool
So, our solution should look like
check str = any ??? (words str)
and all we have to do is figure out the ???
. The elem
function lets us check whether an element in a list:
elem :: (Eq a) => a -> [a] -> Bool
In this case, the list should be the list of months, and the element we're searching for should be the word of the string. So, to fill in the blank:
check :: String -> Bool
check str = any (\word -> word `elem` fullMons) (words str)
(Note: foo `op` bar
is just op foo bar
; a lot of operators are designed to be written and read this way.)
We can make this simpler and more idiomatic by getting rid of the parameter:
check :: String -> Bool
check = any (\word -> word `elem` fullMons) . words
This means that we apply words
to the input, and then apply any (\word -> elem word fullMons)
to the result of words
. You could simplify this further to:
check :: String -> Bool
check = any (`elem` fullMons) . words
(i.e., "do any of the elements of the words
of our input appear in fullMons
?")
but that isn't necessary.
I think the original solution you were trying to get at was to check each month name on the entire string in turn. To do this, we just need to flip the control structure a bit:
check :: String -> Bool
check str = any (\word -> word `elem` ws) fullMons
where ws = words str
(i.e., "do any of the elements of fullMons
appear in words str
?")
Upvotes: 9
Reputation: 125307
You can use the any
function to check if a predicate is true for any member of a list.
Here I have used the isInfixOf
function from Data.List
to make the predicate:
check :: String -> Bool
check str = any (`isInfixOf` str) fullMons
Upvotes: 3