How to search for matching items in a list?

89 views Asked by At

I'm doing an exercise to practice for my exam tomorrow. The text tells me to implement a database to a library, to define Items that can be books or magazines. To each book I save the Name + Author. To each Magazine I save the name:

 data Item = Book String String
      | Magazine String
      deriving(Show)

data Requisition = Req String Item

type Database = [Requisition]

exDB :: Database
exDB = [Req "John" (Book "PF" "HS"),Req "Jay"(Book "Apple" "Steve Jobs"),Req "Francis"(Magazine "Forbes")]

books :: Database -> String -> [Item]
books db name = {-- what's next?-}

Now, I need to create a function named books :: Database -> String -> [Item], that searches by name on my database and gives me the books that person requested.

how do I do this?

2

There are 2 answers

0
bheklilr On

This is fairly straightforward using the filter function:

filter :: (a -> Bool) -> [a] -> [a]

It takes a condition to apply to each element of a list, then returns the list of all elements that meet that condition. In your case, you want to look up what books have been requested by a given person. You can break this down into two problems:

  1. Find all requests for a given person
  2. Find all books in a Requisition list

To solve the first, we say

requestsFromPerson :: Database -> String -> Database
requestsFromPerson db name = filter matchesName db
    where
        matchesName (Req name' item) = name == name'

The second step can also be done with filter, but I'm going to let you fill in the implementation

onlyBooks :: Database -> Database
onlyBooks db = filter ??? db

Then you can combine these two:

books db name = onlyBooks (requestsFromPerson db name)

So all you have to do is fill in the ??? for onlyBooks and this should work! Hint: pattern matching is your friend.

0
Will Ness On
books db name = [... | Req n b@(Book _ _) <- db, n==name]

With list comprehensions, mismatched items are just skipped over. Patterns may be nested.