Alex
Alex

Reputation: 434

How can I zip a list over another list that is nested in Haskell?

so, here's a type definition, just for some context:

type Name = String
type Coordinates = (Int, Int)
type Pop = Int
type TotalPop = [Pop]
type City = (Name, (Coordinates, TotalPop))

And here's a data set:

testData :: [City]
testData = [("New York City", ((1,1), [5, 4, 3, 2])),
           ("Washingotn DC", ((3,3), [3, 2, 1, 1])),
           ("Los Angeles", ((2,2), [7, 7, 7, 5]))]

So, I'm trying to make a function (addAllPops) to edit TotalPop of all City's in [City] with a new entry at the start of TotalPop. I want it to work in such a way that in the example below, the input addNewPop testData [6, 4, 8] would change them to:

"New York City", ((1,1), [6, 5, 4, 3, 2],
"Washingotn DC", ((3,3), [4, 3, 2, 1, 1],
"Los Angeles", ((2,2), [8, 7, 7, 7, 5]

The function to change just one single city's population is here, along with my attempt for the whole, my biggest issue is entirely around collapsing the two lists into one.

addAllPops :: [City] -> [Int] -> [City]
addAllPops [(w, ((x,y), z))] pops = [map uncurry addPop (zip pops z)]

addPop :: City -> Int -> City
addPop (w, ((x,y), z)) p = (w, ((x,y), p:z))

I've been stuck on this for an embarassingly long amount of time, any and all assistance is greatly appreciated :)

Upvotes: 3

Views: 220

Answers (1)

luqui
luqui

Reputation: 60463

Your instinct to start with addPop working one at a time is correct. Now look at the type signature of zipWith:

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

It takes a function which operates pointwise and lifts it to operate on two lists in parallel. So you zipWith the cities and the list of new elements, using addPop to combine them pointwise:

addAllPops :: [City] -> [Int] -> [City]
addAllPops cities newPops = zipWith addPop cities newPops

We can eta-contract this definition to arrive at the surprisingly simple

addAllPops = zipWith addPop

You could have done this with zip and map also, but it's just more plumbing.

Upvotes: 2

Related Questions