列表中的Haskell递归

时间:2015-10-26 20:55:36

标签: list haskell recursion

我有这样的代码:

appd (a:e) ((c,b):bs) | a == c && bs /= [] = b:appd(a:e) bs
                      | a /= c && bs /= [] = appd (a:e) bs
                      | a /= c && bs == [] = appd e ((c,b):bs)
                      | otherwise          = b:appd e ((c,b):bs)

它循环遍历两个列表,如[1,2,3][(1,2),(6,5),(3,5)],并获取第一个列表的第一个元素,并将其与其他列表中每个元组的第一个元素进行比较,如果它们相等则保存第二个元素元组。它工作正常,但如果我采用第一个列表的第二个元素,比较不起作用,在这种情况下2

例如,如果我有[1,2,3][(1,2),(6,5),(3,5)]等列表,则函数从第一个列表中获取1并与1进行比较,然后与6进行比较,然后到3,它可以工作,但它不需要第一个列表的第二个元素 - 2,并且不再进行比较。怎么了?

1 个答案:

答案 0 :(得分:1)

首先,请注意您应该包含您收到的错误消息。您还应该向我们展示一些示例输出和示例输入。

无论如何:您当前的appd无法处理空列表,因此您需要先为此添加案例:

appd _     []          = []
appd []    bs          = snd <$> bs  -- you can decide to use [] instead
appd (a:e) ((c,b):bs)
  | a == c && bs /= [] = b:appd(a:e) bs
  | a /= c && bs /= [] = appd (a:e) bs
  | a /= c && bs == [] = appd e ((c,b):bs)
  | otherwise          = b:appd e ((c,b):bs)

现在你的功能适用于你提供的输入,但我不确定它会返回你想要的结果:

*Main> appd [1,2,3] [(1,2),(6,5),(3,5)]
[2,5,5]

此外,我已经清理了一些代码并使用显式类型签名注释了您的函数:

appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd []         bs      = snd <$> bs
appd _          []      = []
appd as@(a:ass) bs@((c,b):bss)
  | a == c && bss /= [] = b : appd as  bss
  | a /= c && bss /= [] =     appd as  bss
  | a /= c && bss == [] =     appd ass bs
  | otherwise           = b : appd ass bs

,您可以使用更简单的非递归实现来获得与上面相同的结果:

appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd as bs = snd <$> filter (\(a,_) -> a `elem` as) bs

或者如果你喜欢point free(a.k.a。tacit):

appd :: (Eq a, Eq b) => [a] -> [(a,b)] -> [b]
appd as = (snd <$>) . filter ((`elem` as) . fst)

注意: <$>fmap的别名,在列表中使用时,其行为与map完全相同。