1

我正在尝试从本质上是包含混合类型的列表的类型中生成一个新列表。我不确定对此的技术描述,所以我提前道歉,但我认为我可以通过使用示例和代码来解释。

例如,我有一个类型/列表,其中定义了以下类型:

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

testBase :: Database
testBase 
= [("Alice",["TinTin", "Wizard of Oz"]), ("Rory", ["Learn Erlang", "Learn Haskell"]) ]

在上述数据库类型中,我有一个“模拟”库。第一个值 (Person) 是借阅者的姓名,第二个值是列表,包含此人已借阅的所有书籍。

基于这些信息,我希望能够有一个函数来获取这个人的名字,并返回一个他们借过的书的列表。例如,有一个“爱丽丝”的参数应该返回:

 ["TinTin", "Wizard of Oz"]

我创建的函数看起来像这样,但返回一个空列表。我希望它返回一个包含书籍值的列表,即 [Book]。我应该怎么做才能使这段代码工作?

borrowedBooks       :: Database -> Person -> [Book]
borrowedBooks dBase findPerson
=   [book | (person,[book])  <- dBase, person == findPerson ]
4

1 回答 1

8

您的搜索功能包含以下模式匹配:

(person, [book]) <- dBase

回想一下,列表推导生成器中的模式匹配充当过滤器。也就是说,失败的匹配将被丢弃。在您的情况下,您正在对仅包含一本书的书籍列表进行模式匹配。

所以只有那些拥有一本书的人会被退回,这在您的样本数据中是没有人的。

我想你的意思是:

[ books | (person,books) <- dBase, person == findPerson ]

请注意,此处使用列表并不能保证一个人的唯一性——可能有多个人与您的数据类型匹配。列表推导的返回类型揭示了这一点 (a [[Book]]) 列表不会静态地强制键只出现一次。切换到 Data.Map 或其他具有键唯一性保证的关联结构将使这更简单。

于 2012-05-28T18:01:08.830 回答