I’m trying to generate a new list from a type that is essentially a list that contains mixed types. I’m unsure about the technical description of this so I apologize in advance, but I think I can explain by using examples and code.
For example, I have a type/list with the following types defined:
type Database = [(Person, [Book]) ]
type Person = String
type Book = String
testBase :: Database
testBase
= [("Alice",["TinTin", "Wizard of Oz"]), ("Rory", ["Learn Erlang", "Learn Haskell"]) ]
In the above Database type, I have a “simulated” library. The first value (Person) is the named of the borrower, and the second value, the list, contains all the books that the person has borrowed.
Based on this information, I want to be able to have a function that takes the person’s name, and returns a list of the books they have borrowed. For instance, having an argument of “Alice” should return:
["TinTin", "Wizard of Oz"]
The function I created looks like this, but returns an empty list. I want it to return a list containing book values i.e. [Book]. What am I supposed to do to make this code work?
borrowedBooks :: Database -> Person -> [Book]
borrowedBooks dBase findPerson
= [book | (person,[book]) <- dBase, person == findPerson ]
Your search function contains the following pattern match:
Recall that pattern matches in list comprehension generators act as filters. That is, failing matches will be discarded. In your case, you are pattern matching on book lists that contain precisely one book.
So only those people who have one book will be returned, which is no one in your sample data.
I think you mean this:
Note that using lists here doesn’t guarantee the uniqueness of a person — there may be more than one person who matches in your data type. The return type of the list comprehension reveals this (a
[[Book]]) The list doesn’t enforce statically that the key only appears once. Switching to a Data.Map or some other associative structure with a guarantee of key uniquness will make this simpler.