我刚开始学习Haskell,在编写基本函数时遇到了问题。
这个函数应该告诉我一个数组中前一个元素比当前元素大多少个元素。这是代码:
countIncreases :: (Ord a, Num b) => [a] -> b -> b
countIncreases [x] c = c
countIncreases (x:y:r) c
| y > x = countIncreases (y:r) (c+1)
| otherwise = countIncreases (y:r) c
我试着用测试它
countIncreases [1,2] 0
我将所有这些代码粘贴到ghci
中,但得到错误
Non-exhaustive patterns in function countIncreases
然而,我认为这种情况所需的所有模式都是匹配的:
- 第一个iter.:
x = 1
、y = 2
、r = []
和c = 0
。2 > 1
,所以我们进入第一个分支并呼叫countIncreases (2:[]) (0 + 1)
- 第2升:
c = 1
所以返回1
我做错了什么?
如果您运行您的函数,它不会产生错误,但如果您在打开-Wincomplete-patterns
的地方编译代码,并将警告视为错误(-Werror
(,它会在这方面出错。
之所以会发生这种情况,是因为您不能在空列表中运行此函数。实际上,如果使用空列表调用它,[x]
和(x:y:r)
模式都将失败。
如果你计算增加项目的数量,那么对于一个空列表,就没有这样的元素,所以你可以用来实现它
countIncreases :: (Ord a, Num b) => [a] -> b -> b
countIncreases[]c = c
countIncreases[_]c = c
countIncreases (x:r@(y:_)) c
| y > x = countIncreases r (c+1)
| otherwise = countIncreases r c
您忘记考虑空列表([]
(情况:
countIncreases :: (Ord a, Num b) => [a] -> b -> b
countIncreases [x] c = c
countIncreases (x:y:r) c
| y > x = countIncreases (y:r) (c+1)
| otherwise = countIncreases (y:r) c
countIncreases [] c = c -- here!
然而,如果你认为函数永远不应该这样调用,你可能会抛出一个错误:
countIncreases [] _ = error "countIncrease on empty list!"
另一方面,我无法在您的测试中重现错误。
ghci
,并逐行插入重载,认为每一行都会为函数定义添加一个重载。事实证明,每一行我都覆盖了以前的输入。因此,记忆中总是只有最后一个。
从这个问题中,我了解了如何在ghci
中进行多行输入,并了解了我的函数的工作原理。