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

1 つのペアに対しては機能しますが、ペアが上昇していない場合は機能しません。コードに従うと、False が返されるはずです。

4

1 に答える 1

4

[x,y]パターンのガードを詳しく見てください。

ascending [x,y] | y>=x = True
                | x<y  = False

に適用する[2,1]と、最初のガードがチェックされ、次のように評価されますFalse(2 >= 1 であるため)。次に、2 番目のガードがチェックされますが、False(1 < 2 であるため) と評価されます。したがって、次のパターンが使用されます ([2,1]も一致したため(x:y:ys)) が、まったく同じことが起こります。これが最後のパターンだったので、GHCは当然あなたに叫びます.

ガードの不等式は補完的ではありません。3 番目のパターンは次のようになります。

ascending [x,y] | x <= y = True
                | x >  y = False

または、エラーの余地を少なくするために、

ascending [x,y] | x <= y    = True
                | otherwise = False

ただし、改善の余地はまだたくさんあります。特に:

  • 3 番目のパターンは 4 番目のパターンと重複しています。
  • 関数は を返すため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 に答える