如何在 Haskell 中将一个嵌套在另一个列表中的列表压缩成一个列表?

3

所以,这里是一个类型定义,只是为了提供一些背景:

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

这里有一个数据集:

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]))]

所以,我正在尝试编写一个函数(addAllPops)来编辑 [City] 中所有 CityTotalPop,并在 TotalPop 开始处添加一个新条目。 我希望它能按以下示例工作,在下面的示例中,输入 addNewPop testData [6, 4, 8] 将更改它们为:
"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]

这里有一个更改单个城市人口的函数,同时也有我对整体进行尝试的代码,我的最大问题完全在于将这两个列表合并为一个。
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))

我已经被这个问题困扰了很长一段时间,任何帮助都将非常感激 :)

1个回答

2

您先从逐个测试addPop的直觉是正确的。现在看一下zipWith的类型签名:

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

它需要一个逐点操作的函数,并将其提升到并行操作两个列表。因此,您可以使用addPop逐点组合城市和新元素列表,使用zipWith

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

我们可以将这个定义简化为令人惊讶的简单形式。
addAllPops = zipWith addPop

你也可以使用zipmap来完成这个操作,但那样会更加繁琐。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接