带量化类型的ParseError模式匹配非穷尽错误咨询
问题根源:全称量化字段的模式匹配误区
你遇到的模式非穷尽报错,核心问题在于回溯字段的类型设计错误,以及对GHC处理量化类型模式匹配的逻辑理解偏差:
你的回溯字段用了forall d . Maybe (ParseError s d)——这是一个全称量化的多态值,它的含义是「该值可以为任意d类型生成对应的Maybe (ParseError s d)」,而非一个具体的、固定的Maybe值。你在模式匹配里直接写Nothing/Just b,是把它当成普通的Maybe类型值来处理,但GHC无法确认所有多态值都能被这两个模式覆盖(比如存在多态值对某些d返回Nothing,对另一些d返回Just),因此判定模式非穷尽。
而你的实际需求是「回溯链中可以包含任意e类型的错误」,这应该用存在量化(表示「存在某个d类型的错误」),而非全称量化。
修复方案
1. 定义存在类型包装器
先创建一个包装类型,用来封装任意d类型的解析错误:
data SomeParseError s where SomeParseError :: ParseError s d -> SomeParseError s
2. 修改ParseError类型定义
将回溯字段替换为存在类型的Maybe包装:
data ParseError s e where -- | Error with no indication of its origin. Fail :: ParseError s e ParseError :: !Text -- ^ Error message. -> Maybe (SomeParseError s) -- ^ Error backtrace (存在类型封装任意错误) -> !s -- ^ State component. -> !e -- ^ Error component. -> ParseError s e
3. 调整backtrace函数适配新结构
现在可以正常进行模式匹配:
backtrace :: (forall d . Text -> s -> d -> a) -> ParseError s e -> [a] backtrace f = go where go Fail = [] go (ParseError xs Nothing s e) = [f xs s e] go (ParseError xs (Just (SomeParseError b)) s e) = f xs s e : backtrace f b
这样修改后,GHC会认可模式匹配是穷尽的——因为回溯字段现在是普通的Maybe类型,存在类型包装器可以被正常解构。
内容的提问来源于stack exchange,提问作者G. Rodrigues
相关产品推荐
相关产品推荐

