在一个连接到解析的小型库中,我最初有一个以下形式的错误类型(使用 GADT 语法):
data ParseError s e where
-- | Error with no indication of its origin.
Fail :: ParseError s e
ParseError
:: !Text -- ^ Error message.
-> !s -- ^ State component.
-> !e -- ^ Error component.
-> ParseError s e
Text
字段能够将一些信息附加到错误中,s
字段用于捕获解析器的状态(例如源位置、偏移量等)。然而,重要的字段是 e
字段,它充当一种分类标签。通常,它将是单例类型(或者可能是围绕一些额外数据的新类型),或者是此类类型的联积。说EndOfInputError
、ValidationError
、Either EndOfInputError ValidationError
等等
然后我想,为错误添加回溯不是很好吗?鉴于回溯可能包含不同类型
e
的错误,该字段必须是量化类型,因此我们最终得到:
data ParseError s e where
-- | Error with no indication of its origin.
Fail :: ParseError s e
ParseError
:: !Text -- ^ Error message.
-> (forall d . Maybe (ParseError s d)) -- ^ Error backtrace.
-> !s -- ^ State component.
-> !e -- ^ Error component.
-> ParseError s e
在实践中,量化字段是不同
ParseError
的e
列表,因此对于一般处理,我有:
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 b) s e) = f xs s e : backtrace f b
不幸的是,阴谋集团的错误是:
src/Bins/Types/ParseError.hs:38:9: error: [GHC-62161] [-Wincomplete-patterns, Werror=incomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for ‘go’:
Patterns of type ‘ParseError s e’ not matched: ParseError _ _ _ _
|
38 | go Fail = []
| ^^^^^^^^^^^^...
我不明白为什么这会给我一个关于非详尽模式的错误。在我未经训练的眼睛看来,这些方程涵盖了所有可能的情况,因此我显然错过了有关量化类型如何与模式匹配交互的信息。谁能给我解释一下吗?
以防万一,这很重要:语言 GHC2021 和 GHC v9.10.1。需要更多详细信息,请询问。
你所写的内容是,如果我有一个值
ParseError desc stack state err
,那么无论我选择哪种类型的错误,stack
都可以向我提供包含该类型的解析错误。我怀疑您的意图是构建 ParseError
值的人可以选择存储在堆栈中的类型。为了表达这一点,你可以这样写:
ParseError :: forall d.
!Text -- ^ Error message.
-> Maybe (ParseError s d) -- ^ Error backtrace.
-> !s -- ^ State component.
-> !e -- ^ Error component.
-> ParseError s e
您几乎肯定需要对
d
进行某种类型类约束——否则您无法使用该值执行任何操作!
ParseError :: forall d. Exception d
=> !Text -- ^ Error message.
-> Maybe (ParseError s d) -- ^ Error backtrace.
-> !s -- ^ State component.
-> !e -- ^ Error component.
-> ParseError s e
为了保持一致性,我很想将存在的一层向上移动到堆栈中。
data ParseError s where
-- | Error with no indication of its origin.
Fail :: ParseError s
ParseError :: forall e. Exception e
=> !Text -- ^ Error message.
-> Maybe (ParseError s) -- ^ Error backtrace.
-> !s -- ^ State component.
-> !e -- ^ Error component.
-> ParseError s