Haskell初学者,递归函数,列表,错误:非详尽模式

时间:2018-04-29 04:48:54

标签: list haskell recursion

我尝试写一个函数[int] - > int用迭代函数计算整数列表的总和(结果应该等于函数和的构建)

19>sumList :: [Int] -> Int
20>sumList [list] | length[list] > 0  = [list]!!0 + sumList (drop 1 [list])
21>               | otherwise = 0

如果我尝试运行它,这是结果

uebung1.lhs:20:2: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for ‘sumList’:
    Patterns not matched:
        []
        (_:_:_)
Ok, modules loaded: Main.
*Main> sumList []
*** Exception: uebung1.lhs:(20,2)-(21,31): Non-exhaustive patterns in     function sumList

*Main> sumList [3]
*** Exception: uebung1.lhs:(20,2)-(21,31): Non-exhaustive patterns in   function sumListi i i i i 

我做错了什么?我睡了一个晚上,但我只是没有看到问题所在。守卫方程应该捕获列表长度的所有情况。谢谢你的任何建议。

3 个答案:

答案 0 :(得分:2)

问题是你的模式只匹配一个元素的列表。

例如,如果您尝试在ghci中定义一个函数:

a [x] = x

然后尝试使用具有不同数量元素的列表来调用它:

使用a [1]

1结果 使用a []

Exception: <interactive>:5:1-13: Non-exhaustive patterns in function a结果 使用a [1,2]

Exception: <interactive>:1:1-9: Non-exhaustive patterns in function a结果

以下修改使您的功能有效:

sumList :: [Int] -> Int
sumList list | length list > 0  = list!!0 + sumList (drop 1 list)
             | otherwise = 0

但是,当然,以下定义会更具惯用性和高效性:

sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs

(x:xs)模式,您会立即收到x作为列表标题(list!!0)和xs作为其尾部(drop 1 list)< / p>

答案 1 :(得分:1)

该功能不适用于空列表或任何包含多个项目的列表。

您的问题是您与[list]匹配,这是一个名为list的成员列表。相反,请尝试仅匹配list。这意味着它将匹配您的类型签名中[Int]类型的任何内容。

我感到困惑,因为类型[a]适用于任何长度的列表,但[a]只会匹配一个元素的列表。

我还附加了另一种使用模式匹配编写函数的方法,希望你会发现它很有用。

sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs

使用警卫是不寻常的,但是你做了,你的代码看起来像这样:

sumList :: [Int] -> Int
sumList list
    | length list > 0 = head list + sumList (tail list)
    | otherwise = 0

注意[list]如何替换list!! 0替换为headdrop 1已被tail取代}。

Hoogle是你的朋友!

你也可以将空列表的检查移动到第一个警卫,如下所示:

sumList :: [Int] -> Int
sumList list
    | list == [] = 0
    | otherwise = head list + sumList (tail list)

请注意此代码与模式匹配代码的相似之处。

答案 2 :(得分:1)

其他人已经回答了,但我想强调编译器发出的警告发现了这个问题:

Pattern match(es) are non-exhaustive
In an equation for ‘sumList’:
    Patterns not matched:
        []
        (_:_:_)

这就是说代码在模式匹配中没有处理某些情况。上面的空列表[]报告为不匹配,这意味着程序将在空列表中崩溃。此外,表单(_:_:_)的列表不匹配:这些列表包含至少两个元素,例如1:2:rest,这是一个以元素12开头的列表然后继续列表rest以获取下一个元素。

所以,警告告诉我们,我们只处理长度为1的列表。实际上,我们只处理模式[_],它与_:[]相同 - 一个以一个元素开头然后在那里结束的列表。

如果您是初学者,我认为您还没有学习模式匹配。这应该是学习Haskell的首要任务:它是最重要的功能之一。一般来说,如果您的递归代码使用length, !!, tail, head,那么您很可能会做错了。有些地方需要这些功能,但在许多简单的练习中它们不是,模式匹配通常足够和优雅。