我不知道为什么我的函数不能工作。我已经浏览了所有关于非详尽功能的帖子,但据我所见,我的功能满足了所有可能的选择。
ascending :: [Int] -> Bool
ascending [] = error "Empty list given"
ascending [x] = True
ascending [x,y] | y>=x = True
| x<y = False
ascending (x:y:xs) | y>=x = (ascending (y:xs))
| x<y = False
结果:
*Main> ascending []
*** Exception: Empty list given
*Main> ascending [1]
True
*Main> ascending [1, 2]
True
*Main> ascending [2, 1]
*** Exception: test01.hs:(51,1)-(56,55): Non-exhaustive patterns in function ascending
它适用于一对,但如果这对不是上升的,则无效。当我遵循我的代码时,它应该只是返回False。
仔细查看[x,y]
模式的防护装置:
ascending [x,y] | y>=x = True
| x<y = False
当应用于[2,1]
时,第一个保护被检查并评估为False
(因为2>=1);然后,检查第二保护,但它也评估为False
(因为1<2)。因此,使用了下一个模式(因为[2,1]
也与(x:y:ys)
匹配),但发生了完全相同的事情。因为这是最后一种模式,GHC理所当然地向你尖叫。
你的卫士中的不平等现象并不是互补的。你的第三种模式应该是
ascending [x,y] | x <= y = True
| x > y = False
或者,为了减少出错的空间,
ascending [x,y] | x <= y = True
| otherwise = False
然而,仍有很大的改进空间。特别是:
- 第三种图案与第四种图案重叠
- 因为函数返回
Bool
,所以只使用保护显式返回布尔值是多余的 - 因为,按照惯例(见dfeuer的评论),空列表被认为是升序的,所以你不需要在遇到它时抛出错误(除非你遵循自己异想天开的惯例)
考虑到这一切,你可以简单地编写
ascending :: [Int] -> Bool
ascending (x:y:xs) = x <= y && ascending (y:xs)
ascending _ = True
最后,您可以使用and
和zipWith
:的组合来进一步压缩代码
ascending :: [Int] -> Bool
ascending xs = and $ zipWith (<=) xs (tail xs)