如何在这个实例中应用使用地图?

时间:2012-01-04 21:26:13

标签: haskell

我有一个月份和字符串列表。我想检查字符串中是否有任何月份。我还有一个函数,可以搜索字符串中的单词。我是否必须重写该功能,或者使用某种形式的地图是否可以这样做?

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,所以对我的代码的任何其他评论表示赞赏。感谢

3 个答案:

答案 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