0

How can I add a list to a list of lists? Say I want to add itemz to bagList, which is a list of lists. How can I do that?

bagList itemz = mappend bagList itemz               
jub0bs
  • 60,866
  • 25
  • 183
  • 186
Vlad Balanescu
  • 664
  • 5
  • 27

1 Answers1

2

You might want to consider adding it at the front, this is faster:

bagItem bag item = item : bag

Also it looks like you're coming from an imperative mindset, the way you use bagList before and after the = is not quite right: the expressions before and after the = do not really represent the same construction. Before the = bagItem is used as a function, after the = it's used as some Monoid (which if itemz is a list would also need to be a list).

If you really do want to append the item (this will be slower, because the operation will require going all the way through the list to add the new item at the end, and the whole list will need to be reconstructed) you can do what Christoph suggests or you can go for a recursive formulation something like this:

appendItem :: a -> [a] -> [a]
appendItem i (x:xs) = x : appendItem i xs
appendItem i [] = i : []

If you both want to append and are also worried about performance, you should have a look at difference lists, for example look for the section on difference lists in this chapter in Learn You a Haskell.


Update

From the comments it seems what you are actually looking for is Maps. We can make a Map with each item as a key, and the number of occurrences as the value. In your case it seems this will be a Map String Int.

import Data.List (foldl')
import qualified Data.Map as M

bag :: M.Map String Int
bag = M.empty

addToBag :: M.Map String Int -> [String] -> M.Map String Int
addToBag = foldl' go
  where go m i = M.insertWith (+) i 1 m

main = print $ addToBag bag ["a","b","c","a"]
-- fromList [("a",2), ("b", 1), ("c", 1)]
Sam van Herwaarden
  • 2,321
  • 14
  • 27
  • Got It. Thanks so much for your detailed explanation up there. So basically, if I want to create a data structure to store the items in a bag, and their number, can I create something like: bag :: Eq a => [a]->[a]->[a] – Vlad Balanescu Oct 05 '15 at 07:13
  • bag :: Eq a => [a]->[a]-[a] bag items nr = if null items || null nr then append bagItems [] else append bagItems items append bagItemsNr nr ? Can I do something like that for storing the elemesnt and numbers of items in each bg – Vlad Balanescu Oct 05 '15 at 07:20
  • @user9515: This is starting to sound like a separate question. I would probably not store the number of items in each set separately because you run the risk of the numbers somehow running out of sync with the item sets. After all, it is also very easy to retrieve the number of items in each sublist: `map length bag`. If you really do want to store the number with each set of items, I would probably choose a `bag :: [(Int, [a])]` where the lists of items are stored together with their length in the bag. You would then add items as such: `bagItems bag items = (length items, items) : bag`. – Sam van Herwaarden Oct 05 '15 at 07:45
  • Yeah, but what if I have for example: ["a","b","c","c","c"] -> I want to store this list for example. Should I use something like: bag:: [(Int,[a])] and then call bagItems bag items = (length items, items) : bag I mean I have different items in each bag? How can I store them in the most quickest way possible? Really new to this kind of programming, and it's just for curiosity. Thanks! – Vlad Balanescu Oct 05 '15 at 09:07
  • Until now I was thinking like bag :: Eq a => [a] -> [a] bagItems :: bag -> [] -> [[String]] bagItems bag items = ([ items length ]) .... – Vlad Balanescu Oct 05 '15 at 09:11
  • @user9515: I'm not sure I understand what you want. If `itemz` is a list of strings, `bag` will technically be a list of lists of lists (because strings are lists as well). So I'm not sure if your example is an item in the bag or the bag itself. I also don't know what you mean with your type statement `bag :: Eq a => [Int] -> [a]` - think about it: you can't just create a list of any (Eq) type from only a list of integers as input. – Sam van Herwaarden Oct 05 '15 at 09:17
  • @user9515: You seem to be misunderstanding some quite fundamental principles behind the Haskell type system. Maybe you should spend some more time with (for example) [Learn You A Haskell](http://learnyouahaskell.com/chapters). – Sam van Herwaarden Oct 05 '15 at 09:21
  • So my question is, how can I store a list of items, for example ["a","a","b","c","c"] in a haskell programme efficiently, so for example, storing a list of items, say ["a","b","c"] then a list of the numbers of those items [2,1,2]. Can I use bags to help me solve this question? Can u put a piece of code here, regarding storing this numbers? I would appreciate it! – Vlad Balanescu Oct 05 '15 at 09:26
  • @user9515: Ok I think I understand what you were looking for now, although it was not so clear from the question. See my updated answer. Documentation for Data.Map is [here](http://hackage.haskell.org/package/containers-0.5.6.3/docs/Data-Map.html) and usage is also explained in Real World Haskell and I think Learn You A Haskell as well. – Sam van Herwaarden Oct 05 '15 at 10:07
  • Got it now. And if I want to save more than one bag? For example, each bag has certain items, so, I don't basically add to.each bag, but I want to.save each bag to an array of bags or something like that – Vlad Balanescu Oct 05 '15 at 10:56
  • As with any type you can make a list of `Map`s. If you have a `[[String]]` you can use `map (addToBag bag) itemlists` to make a `[Map String Int]`. If you want you can even use another layer of `Map`s, i.e. `Map String (Map String Int)`. – Sam van Herwaarden Oct 05 '15 at 11:03
  • bagsList :: [[M.Map String Int]] bagsList = [[]] addToBag :: M.Map String Int -> [String] -> M.Map String Int addToBag = foldl' go where go m i = M.insertWith (+) i 1 m bagsList.append (go) Should this be the one? Not quite sure how to append it to a list of lists, and which is the parameter. Is it go, after that where? – Vlad Balanescu Oct 05 '15 at 13:21
  • @user9515: I can't make sense of this amount of code in comments. If you understand the solutions I've presented (i.e. how they work) I think you have all the information you need to accomplish what you want. If you don't understand the code, take your introductory Haskell guide of choice (real world haskell or learn you a haskell) and look up the necessary concepts, I think you'll be able to figure it out. If you run into problems with your code ask a different question, this discussion is going too far off-topic from your original question. – Sam van Herwaarden Oct 05 '15 at 13:48