我尝试写一个函数[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
我做错了什么?我睡了一个晚上,但我只是没有看到问题所在。守卫方程应该捕获列表长度的所有情况。谢谢你的任何建议。
答案 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
替换为head
,drop 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
,这是一个以元素1
和2
开头的列表然后继续列表rest
以获取下一个元素。
所以,警告告诉我们,我们只处理长度为1的列表。实际上,我们只处理模式[_]
,它与_:[]
相同 - 一个以一个元素开头然后在那里结束的列表。
如果您是初学者,我认为您还没有学习模式匹配。这应该是学习Haskell的首要任务:它是最重要的功能之一。一般来说,如果您的递归代码使用length, !!, tail, head
,那么您很可能会做错了。有些地方需要这些功能,但在许多简单的练习中它们不是,模式匹配通常足够和优雅。