1

我不知道为什么我的功能不起作用。我浏览了所有关于非详尽功能的帖子,但据我所知,我的功能满足了所有可能的选择。

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。

4

1 回答 1

4

仔细查看您的[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

但是,仍有很大的改进空间。尤其是:

  • 第三个图案与第四个图案重叠。
  • 因为您的函数返回 a 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)
于 2015-02-08T00:34:43.373 回答