Haskell函数checkDirecRio非穷尽模式问题求助
解决Haskell中checkDirecRio函数的非穷尽模式问题
问题描述
你的checkDirecRio函数编译通过,但调用时触发Non-exhaustive patterns错误,函数需求为:验证相邻Rio的方向,若存在相邻Rio方向相反则返回True,所有相邻Rio方向均相同(或无相邻Rio)则返回False。
数据结构定义
type Velocidade = Int data Mapa = Mapa Largura [(Terreno, [Obstaculo])] deriving (Show, Read, Eq) data Terreno = Rio Velocidade | Estrada Velocidade | Relva deriving (Show, Read, Eq) data Obstaculo = Nenhum -- ^ nothing | Tronco -- ^ wood who can only in Rio being | Carro -- ^ car who can only in Estrada being | Arvore -- ^ tree who can only in Relva being deriving (Show, Read, Eq)
原始出错代码
checkDirecRio :: Mapa -> Bool checkDirecRio (Mapa _ []) = True checkDirecRio (Mapa larg ((Rio x, _) : (_,_) : t)) = checkDirecRio (Mapa larg t) checkDirecRio (Mapa larg ((Rio x, _) : (Rio y, _) : t)) | ((x > 0 && y < 0) || (x < 0 && y > 0)) = True | otherwise = checkDirecRio (Mapa larg t)
问题根源
函数未覆盖所有输入场景,遗漏了:
- 列表仅剩单个元素的情况(无论地形类型)
- 第一个元素不是
Rio的情况(比如开头是Estrada或Relva) - 处理相邻
Rio时跳过了连续多Rio的检查(比如[Rio x, Rio y, Rio z]会直接跳到z,忽略y和z的相邻检查)
修复后的代码
checkDirecRio :: Mapa -> Bool checkDirecRio (Mapa _ []) = False -- 无相邻地形,不存在相反方向的Rio checkDirecRio (Mapa larg (_ : [])) = False -- 单个元素,无相邻地形可检查 checkDirecRio (Mapa larg ((Rio x, _) : (Rio y, _) : t)) | (x > 0 && y < 0) || (x < 0 && y > 0) = True -- 发现方向相反的相邻Rio,直接返回True | otherwise = checkDirecRio (Mapa larg ((Rio y, _) : t)) -- 保留第二个Rio,继续检查后续相邻对 checkDirecRio (Mapa larg (_ : t)) = checkDirecRio (Mapa larg t) -- 第一个元素非Rio,跳过并检查剩余列表
代码逻辑说明
- 空列表/单个元素:直接返回
False,因为没有相邻地形可以验证。 - 相邻两个都是Rio:
- 若速度符号相反(方向相反),立即返回
True,满足需求。 - 若方向相同,将第二个
Rio作为新的起始元素,继续检查后续列表,避免遗漏连续Rio的相邻检查。
- 若速度符号相反(方向相反),立即返回
- 第一个元素非Rio:跳过当前元素,递归检查剩余列表。
内容的提问来源于stack exchange,提问作者Filipe Chehab
相关产品推荐
相关产品推荐

