我有一个月份和字符串列表。我想检查字符串中是否有任何月份。我还有一个函数,可以搜索字符串中的单词。我是否必须重写该功能,或者使用某种形式的地图是否可以这样做?
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,所以对我的代码的任何其他评论表示赞赏。感谢
答案 0 :(得分: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
的任何元素?”
答案 1 :(得分:3)
您可以使用any
函数检查列表中任何成员的谓词是否为真。
在这里,我使用isInfixOf
中的Data.List
函数来制作谓词:
check :: String -> Bool
check str = any (`isInfixOf` str) fullMons
答案 2 :(得分: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
使用类型,然后从那些类型转换为字符串表示形式,如:
show April