在GHCi中声明函数时出现“Non exhaustive patterns in function”错误原因咨询
为什么GHCi中逐行定义Haskell函数会触发非穷尽模式错误,而加载模块却正常?
这个问题的核心差异在于GHC交互模式(GHCi)和模块编译模式对多模式函数定义的处理方式完全不同:
模块中的函数定义
在sum.hs模块里,你写的两行模式定义属于同一个函数的完整定义:
sum' :: (Num a) => [a] -> a sum' [] = 0 sum' (x:xs) = x + sum' xs
GHC在编译模块时,会自动把这些模式分支合并成一个覆盖所有可能情况的函数:空列表直接返回0,非空列表则递归拆分计算。当递归到空列表时,能匹配到第一个分支,自然不会出现非穷尽模式的问题。
GHCi中的逐行定义
而在GHCi里,默认情况下,每一行单独的函数定义都会完全覆盖之前的同名函数,不是给已有函数补充模式分支:
- 输入第一行
sum' [] = 0时,GHCi定义了一个仅处理空列表的sum'——这时候调用非空列表会报错,但调用空列表能正常返回0。 - 输入第二行
sum' (x:xs) = x + sum' xs时,GHCi会直接替换掉之前的sum'定义,现在的sum'只有非空列表的处理逻辑,完全丢失了空列表的分支。
这时候调用sum' [3,4],函数会先匹配3:[4],计算3 + sum' [4];接着sum' [4]匹配4:[],计算4 + sum' [];但此时sum'没有定义空列表的处理分支,递归到这里就触发了非穷尽模式的异常——这就是你看到的错误。
如何在GHCi中正确定义多模式函数
如果想在GHCi中定义带有多个模式的函数,你需要把所有模式放在同一个输入块里,用:{和:}包裹:
Prelude> :{ Prelude| sum' [] = 0 Prelude| sum' (x:xs) = x + sum' xs Prelude| :} Prelude> sum' [3,4] 7
这样GHCi就会把这些行当作同一个函数的完整定义处理,和模块中的行为完全一致。
内容的提问来源于stack exchange,提问作者laker93
相关产品推荐
相关产品推荐

