Dan
Dan

Reputation: 39

Recursion over list inside list

I have some code like this:

data Set = Set String [Int]
  deriving (Show, Read)
getArr :: Set -> [Int]
getArr (Set _ arr) = arr

My goal is to write a function that will input a list of values into a tuple. EG: data -- "One" [1], "Two" [2], "Three" [3] output: "One" [0, 1], "Two" [1,2], "Three" [3,3] with the input being [0, 1, 3]

My general aproach to this was to go recursively over the data going one by one and at the same time going over the list of values one by one using : to add it onto the first index.

I attempted to do something like:

addToSet :: [Set] -> [Int] -> [Set]
addToSet [] [] = []
addToSet (x:xs) (y:ys) = (getArr x : y) ++ addToSet xs

but i get an error saying :

Couldn't match type ‘[Int]’ with ‘Set’
  Expected type: [Set]
    Actual type: [[Int]]```

Upvotes: 1

Views: 62

Answers (1)

chepner
chepner

Reputation: 532368

Consider the helper function

updateSet :: Set -> Int -> Set
updateSet (Set s xs) y = Set s (y:xs)

This simply adds a single value to a given set:

>>> updateSet (Set "One" [1]) 0
Set "One" [0,1]

Then addToSet is just a wrapper around zipWith:

addToSet :: [Set] -> [Int] -> [Set]
addToSet = zipWith updateSet

updateSet is called on the first set and the first integer, then the second set and the second integer, and so on, with the results combined in order in a single list.


Another way to think of this is mapping a function of type (Set, Int) -> Int over the result of zipping the two lists together:

updateSet' :: (Set, Int) -> Set
updateSet' (Set s xs, y) -> Set s (y:xs)

addToSet :: [Set] -> [Int] -> [Set]
addToSet ss is = map updateSet' (zip ss is)

Note that updateSet' = uncurry updateSet.

Upvotes: 1

Related Questions