您如何对列表中一对的各个元素求和?

时间:2019-03-05 23:20:50

标签: haskell pattern-matching

我正在尝试从列表中获取该对中的第一个和第二个元素,以便可以对其求和。这是我的代码,我不确定为什么会出现错误

@property (nonatomic, weak, nullable) id<NetworkerDelegate> delegate;

1 个答案:

答案 0 :(得分:7)

首先,让我们采用当前无效的定义:

func :: [(Double,Double)] -> (Double,Double)
func [(x, y)] = map fst (x,y)

这有几处错误:

  • 您的模式匹配[(x, y)]仅匹配具有一个元素的列表。任何包含2个或更多元素的列表都将导致错误,因为它们不匹配。
  • map不能应用于元组;它只能应用于列表。
  • 即使可以在元组上map,也必须直接将fst应用于元组-fst (a, b)给出a,而map fst (a, b)则不然有道理。

让我们看看一些替代定义。

列表理解

func_1 :: [(Double,Double)] -> (Double,Double)
func_1 list =
    let fsts = [ a | (a, _) <- list ]
        snds = [ b | (_, b) <- list ]
    in (sum fsts, sum snds)

这将分别从列表中提取每个第一个元素,然后从列表中提取每个第二个元素,然后将它们添加在一起。

映射

func_2 :: [(Double,Double)] -> (Double,Double)
func_2 list =
    let fsts = map fst list
        snds = map snd list
    in (sum fsts, sum snds)

在输入列表的每个元素上映射fst,以获取列表中所有第一元素的列表。然后映射snd对第二个元素执行相同的操作。

递归

func_3 :: [(Double,Double)] -> (Double,Double)
func_3 [] = (0, 0)
func_3 ((a,b) : xs) =
    let (a', b') = func_3 xs
    in (a+a', b+b')

有些不同的方法。 Haskell中的列表是递归形成的:[a, b, c]等效于(a : (b : (c : [])))。这意味着我们可以使用模式匹配来获取列表的第一个元素以及列表的所有其他元素。此定义分为两个部分:

  • 如果列表中没有元素,则仅返回(0, 0)基本情况)。
  • 如果列表中至少有一个元素,请使用列表的其余部分(例如,如果给出了[b, c],则为[a, b, c];如果给出了[],则为[a]),再次使用func_3计算其总和,然后再添加第一个元素。