我已经和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;我无法弄清楚为什么我的语法不起作用。有什么建议吗?
答案 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)
只是一个子内容。
您可能不熟悉all
,uncurry
以及zip
,所以让我详细说明。 zip
具有函数签名zip :: [a] -> [b] -> [(a,b)]
,因此它需要两个列表并将它们的元素配对(如果一个列表比另一个列表长,它只会删除多余的列表)。 uncurry
很奇怪所以我们只看(uncurry (==))
,它的签名是(uncurry (==)) :: Eq a => (a, a) -> Bool
,它实质上检查对中的第一个和第二个元素是否相等。最后,all
将遍历列表并查看每对中的第一个和第二个是否相等,如果是这种情况则返回true。