首页 > 解决方案 > 列表元组的函数

问题描述

如果这个问题非常琐碎,我很抱歉,但我已经努力寻找答案很长一段时间了,这就是我决定在这里发布它的原因。

我想构建一个函数,它采用二进制元组列表: [(Integer, Integer)] 并从所有元组的所有第二个整数中输出最大整数。我写了以下代码:

maxSecond:: [(Integer,Integer)] -> Integer
maxSecond [(ks, as)] = aux (unzip [(ks, as)])
  where aux ([ks],[as]) = maximum ([as])

但它只有在我输入一个只有 1 个元组的列表并为超过 2 个元组的列表输出“函数中的非详尽模式”错误时才有效。我的问题不是如何实际解决原始问题,而是为什么这种方法在 Haskell 中不起作用?

我还编写了以下函数:

aaa:: ([Integer], [Integer]) -> Integer
aaa ([as],[ms]) = 10

显然不可能在 Haskell 中输入列表元组(除非列表不是由 1 个元素组成的)。对此有什么解释吗?

谢谢!!

标签: listhaskelltuples

解决方案


初学者 Haskell 程序员常犯的一个错误是他们认为这[x]是一个匹配任意长度列表的模式。但[x]实际上是一种匹配单例列表的模式(一个只有一个元素的列表,并且该元素“链接”到x)。

如果我们希望能够处理空列表([])或非空列表(长度大于零),我们可以写为 pattern xx而不是“链接”到该列表本身。请注意,我们可以使用任何我们想要的标识符。列表的模式匹配当然很有用:例如处理空列表、cons、恰好包含一、二、三、五等元素的列表的情况。但在这里我们只会限制自己,让事情变得更复杂。

为了计算元组的第二项的最大值,我们可以通过首先map生成一个元素列表的 ping 来处理它,每个元素都是对应元组的第二项,然后我们可以计算该maximum列表的:

maxSecond :: Ord a => [(a, a)] -> a
maxSecond xs = maximum (map snd xs)

因此,我们在这里使用该map :: (a -> b) -> [a] -> [b]函数将函数应用于列表中的所有元素xs,该函数snd :: (c, d) -> d因此采用 2 元组的第二个元素,然后我们计算maximum :: Ord e => [e] -> e以获得该列表的最大值。

我们也可以使用(.) :: (b -> c) -> (a -> b) -> a -> c操作符,写成这样:

maxSecond :: Ord a => [(a, a)] -> a
maxSecond = maximum . map snd

推荐阅读