如何找到一个列表作为另一个列表的子列表出现的索引?

时间:2015-04-08 13:46:58

标签: list haskell recursion sublist

我已经和Haskell一起工作了一个多星期了,所以我正在练习一些可能对某些东西有用的功能。我想递归地比较两个列表。当第一个列表出现在第二个列表中时,我只想返回列表开始匹配的索引。索引将从0开始。以下是我想要执行澄清的示例:

subList [1,2,3] [4,4,1,2,3,5,6] 

结果应为2

我试图对其进行编码:

subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
        where select []     = []
              select (x:xs) = x

我收到输入&#34;错误#34;我无法弄清楚为什么我的语法不起作用。有什么建议吗?

1 个答案:

答案 0 :(得分:2)

让我们先看一下函数签名。您想要接受两个列表,其内容可以进行相等性比较并返回索引,如此

subList :: Eq a => [a] -> [a] -> Int

所以现在我们对参数进行模式匹配。首先,当第二个列表为空时,我们无能为力,因此我们将返回-1作为错误条件

subList _ [] = -1

然后我们看一下递归步骤

subList as xxs@(x:xs)
  | all (uncurry (==)) $ zip as xxs = 0
  | otherwise                       = 1 + subList as xs

您应该熟悉我使用过的防护语法,尽管您可能不熟悉@语法。从本质上讲,如果我们使用xxs,则(x:xs)只是一个子内容。

您可能不熟悉alluncurry以及zip,所以让我详细说明。 zip具有函数签名zip :: [a] -> [b] -> [(a,b)],因此它需要两个列表并将它们的元素配对(如果一个列表比另一个列表长,它只会删除多余的列表)。 uncurry很奇怪所以我们只看(uncurry (==)),它的签名是(uncurry (==)) :: Eq a => (a, a) -> Bool,它实质上检查对中的第一个和第二个元素是否相等。最后,all将遍历列表并查看每对中的第一个和第二个是否相等,如果是这种情况则返回true。