0

我有:

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"])]

如果我要求说“Carol”,它应该返回 [“Game of Thrones”]。

4

3 回答 3

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
于 2013-02-03T22:48:19.567 回答
2

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

也就是说,使用列表理解的解决方案

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

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

同样,这为标准库中已经存在的函数实现了一种解决方法,并且通常可读性较差。真的,使用lookup.

于 2013-02-03T23:36:08.427 回答
1

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

您正在寻找的是 Prelude 函数查找

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

如您所见,如果a ~ Personb ~ [Book]交换参数之后,它几乎具有正确的类型。既然你想要[Book]回来而不是Maybe [Book]你可以把整个东西包裹在fromMaybe里面,结果是:

books db = fromMaybe [] . flip lookup db
于 2013-02-03T22:55:38.280 回答