如何摆脱 Haskell 中的非穷举模式错误?

问题描述

我对 Haskell 很陌生,所以恐怕我还没有完全理解它是如何工作的。下面的方法应该是判断一个矩阵是否是一个实际的矩阵。

isMatrix :: [[Int]] -> Bool
isMatrix [[x]] = True 
isMatrix [x] = True

例如,isMatrix [[1,2],[3,2]] 应该为真,而 [[1],2]] 应该为假。

现在我收到错误消息“isMatrix 函数中的非穷尽模式”。 我是否缺少某些案例,如果是,我该怎么办?

如果有人能向我解释一下,我将不胜感激。

提前致谢!

解决方法

您可以通过使用 -Wall 标志打开警告来询问编译器有关缺失情况的信息。我强烈建议始终启用警告。对于您的代码,编译器报告:

example.hs:11:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for `isMatrix':
        Patterns not matched:
            []
            ([]:_:_)
            ([_]:_:_)
            ((_:_:_):_:_)

这些是您不处理的情况:

  • [] 空矩阵,没有行
  • []:_:_ 一个至少有两行的矩阵,第一行为空
  • [_]:_:_ 一个至少有两行的矩阵,第一行只有一个元素
  • (_:_:_):_:_ 一个至少有两行的矩阵,第一行至少有两个单元格

这是因为 [x] 是一个长度为 one 的列表,在您的情况下是一个只有一行 x 的矩阵。此外,[[x]] 是一个只有一行只有一个元素 x 的矩阵(顺便说一句,不要对行和单元格使用相同的变量名称,这会造成混淆)。许多其他情况未指定。

请注意,即使在您处理的情况下,您的代码也是错误的:例如,isMatrix [[1,2,3,4,5]] 返回 True,因为它只有一行,但这不是矩阵。

有很多方法可以解决您的问题。您可以计算第一行的长度并检查所有其他行:

isMatrix []          = True
isMatrix (row1:rows) = allOfLength (length row) rows
   where
   allOfLength n rows = ....

或者,使用map length预先计算所有行的长度,然后检查结果列表是否由相同的数字组成,重复:

isMatrix mat = allEqual (map length mat)
   where
   allEqual lengths = ....