You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带量化类型的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:53:29