Haskell - 在列表中的元组内列出列表的理解

时间:2013-02-03 22:40:01

标签: list haskell tuples list-comprehension

我有:

type Person     = String
type Book       = String
type Database   = [(Person,[Book])]

我试图定义一个函数:

books :: Database -> Person -> [Book]

接受 1)元组列表(包含字符串和字符串列表 2)字符串名称

并返回一个字符串列表(即数据库中的书籍)

我想使用列表推导,但我不知道如何访问数据库列表中元组内的列表中的元素。

思想?

示例数据库如下所示:

db = [("Bob", ["Red Riding Hood", "Alice in Wonderland"]), ("Carol", ["Game of Thrones"])]

如果我要求说出#34; Carol",它应该返回["权力的游戏"]。

3 个答案:

答案 0 :(得分:3)

由于您有关联列表,因此可以使用lookup功能。它几乎与你想要的一样:

getVal :: Database -> String -> Maybe [String]
getVal  = lookup

唯一的区别是它返回Maybe但是恕我直言,这是正确的行为,考虑如果你在查找数据库时没有数据库会发生什么?

由于您希望使用模式匹配,因此lookup

的来源
lookup                  :: (Eq a) => a -> [(a,b)] -> Maybe b
lookup _key []          =  Nothing
lookup  key ((x,y):xys)
    | key == x          =  Just y
    | otherwise         =  lookup key xys

或者在你的情况下

getVal :: Database -> String -> [String] --Avoids a Maybe if you want
getVal _key []          =  []
getVal  key ((x,y):xys)
    | key == x          =  y
    | otherwise         =  getVal key xys

答案 1 :(得分:2)

正如其他海报所说,lookup是这里的方法:这是在关联列表中搜索某些东西的标准程序。

尽管如此,使用列表理解的解决方案将是

books :: Database -> Person -> [Book]
books db authorName = [book | (author, bookName) <- db,
                              author == authorName
                              book <- bookName]

它逐个取出(author, bookName)元组,丢弃作者不匹配的元组。如果然后将该作者的书籍添加到结果中。

同样,这为已经在标准库中的函数实现了一种变通方法,并且它通常不太可读。真的,使用lookup

答案 2 :(得分:1)

我不会使用列表推导来实现该功能 - 列表推导更适合构建列表。

您要找的是Prelude功能lookup

lookup :: Eq a => a -> [(a, b)] -> Maybe b

正如您所看到的,它几乎具有正确的类型,如a ~ Personb ~ [Book]以及交换参数后。既然您想要[Book]而不是Maybe [Book],那么您可以将整个内容包装在fromMaybe中,从而产生:

books db = fromMaybe [] . flip lookup db