Hi

Basically I've got the following code.
- What it does is it takes two input the itemName and the sectionName
- checks if the input is equal to any item in the list (test database) and increment it
- prints the modified list

It does what it needs to do but when I try to increment the amount of sales for apple the output doubles the record of the apple. someone told me that I should try list comprehension but got no idea of how to use it, im a total beginner and would appreciate a step by step explanation :)

Input Code:

items :: [Grocery]
items = [("Water", "Drink Section", 1),
         ("Squash", "Drink Section", 1),
         ("Apple", "Fruit Section", 1),
         ("Plates", "Disposable Section", 1),
         ("Plates", "Ceramic Section", 1)]

sales:: [database] -> String -> String-> [database]
sales db itemName sectionName = []
sales ((item, section, qty): xs) itemName sectionName 
     | item == itemName && section== sectionName = [(item, section, qty + 1)] sales xs itemName sectionName
     | otherwise = sales xs itemName sectionName

Current Output:

[("Apple", "Fruit Section", 2),
 ("Water", "Drink Section", 1),
 ("Squash", "Drink Section", 1), 
 ("Apple", "Fruit Section", 1),
 ("Plates", "Disposable Section", 1),
 ("Plates", "Ceramic Section", 1)]

Thank You!

I can't reproduce the behavior you're describing.

Your code doesn't produce the output you say it does - your code doesn't even compile. If I correct the code's syntax error, the result will always be the empty list because you have overlapping cases with the less specific case coming first. If I rearrenge the order of your cases, I get the correct output and no entries are duplicated.

Regarding list comprehensions: In its simplest form a list comprehension has the form [expressionInvolving item | item <- items]. This will evaluate the expression expressionInvolving item for every item in the list items. For example you can use a list comprehension to replace each occurence of the string "foo" with "bar" in a list of strings like this:

strings = ["foo", "lala", "lulu", "foo", "baz"]
newstrings = [if string == "foo" then "bar" else "string" | string <- strings]

Now newstrings will be ["bar", "lala", "lulu", "bar", "baz"]. The same logic can be applied to solve your problem.

Note that in simple cases like this a single call to map can do the same thing as the list comprehension. Also in real code I would move the if-then bit in its own named function for readability.

hi again
I was able to create it and get a record just wondering how to get the rest of the list?
thank you!

I'm not sure what you mean by that. Both using a list comprehension or fixing the code in your originial post will give you a whole list as the result, not a single record.

sales testDb item sec = [ (i,s,q+1) | (i,s,q) <- testDb, i == item && sec == s ]
hi sorry, i'm using list comprehension now and have the code above and it only returns a single record

Edited 4 Years Ago by MGibson019

It contains a list with a single record in it. That's because you added a condition to the generator. That's not what I did in my example.

In my example I had a simple generator without a condtion attached to it. I then used if-then-else in the body of the list comprehension to replace matching items and keep all other items unchanged. If you do the same thing, you'll get the result you want.

This article has been dead for over six months. Start a new discussion instead.