Haskell:从混合类型列表中设置生成

Lee*_*res 1 haskell list generator set

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

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

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

testBase :: Database
testBase 
= [("Alice",["TinTin", "Wizard of Oz"]), ("Rory", ["Learn Erlang", "Learn Haskell"]) ]
Run Code Online (Sandbox Code Playgroud)

在上面的数据库类型中,我有一个"模拟"库.第一个值(Person)是借款人的名字,第二个值(列表)包含该人借来的所有书籍.

基于这些信息,我希望能够拥有一个获取该人姓名的功能,并返回他们借来的书籍清单.例如,有一个"Alice"参数应该返回:

 ["TinTin", "Wizard of Oz"]
Run Code Online (Sandbox Code Playgroud)

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

borrowedBooks       :: Database -> Person -> [Book]
borrowedBooks dBase findPerson
=   [book | (person,[book])  <- dBase, person == findPerson ]
Run Code Online (Sandbox Code Playgroud)

Don*_*art 8

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

(person, [book]) <- dBase
Run Code Online (Sandbox Code Playgroud)

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

因此,只有那些拥有一本书的人才会被退回,这在您的样本数据中是没有人的.

我想你的意思是:

[ books | (person,books) <- dBase, person == findPerson ]
Run Code Online (Sandbox Code Playgroud)

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

  • 而且,考虑到所使用的数据结构,简单的"查找"就足够了.`borrowedBooks = flip lookup`. (4认同)