如何让 GHC 对 do 块中的不完整模式绑定发出警告?

Posted

技术标签:

【中文标题】如何让 GHC 对 do 块中的不完整模式绑定发出警告?【英文标题】:How can I get GHC to warn about incomplete pattern bindings in do blocks? 【发布时间】:2016-10-07 20:54:47 【问题描述】:

以下 Haskell 程序已损坏,因为它执行了不完整的模式绑定:

main = do
  [x] <- pure ["foo", "bar"]
  print x

如果你编译它,你不会收到任何警告:

$ ghc -fwarn-incomplete-uni-patterns -o example example.hs
[1 of 1] Compiling Main             ( example.hs, example.o )
Linking example ...

但如果你运行它,你会得到:

example: user error (Pattern match failure in do expression at example.hs:2:3-5)

我想以某种方式获得编译器警告。

从文档中,我原以为 -fwarn-incomplete-uni-patterns 会这样做,因为 do 块去糖:

desugared = pure ["foo", "bar"] >>= \[x] -> print x

确实,将其添加到示例文件中确实会产生警告:

$ ghc -fwarn-incomplete-uni-patterns -o example example.hs
[1 of 1] Compiling Main             ( example.hs, example.o )

example.hs:1:37: Warning:
    Pattern match(es) are non-exhaustive
    In a lambda abstraction:
        Patterns not matched:
            []
            _ : (_ : _)

当我在 do 块内执行相同操作时,如何收到类似的警告?

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.3

【问题讨论】:

请注意,带有&lt;- 的不完整模式最终会调用该monad 的fail 函数。所以至少在旧版本的 Haskell 中,代码本身并没有错,可能会有有效的结果:Prelude&gt; let x::[Int]; x = do [y] &lt;- return [1,2]; return y Prelude&gt; x [] 或者将x :: [Int] 更改为x :: Maybe Int 你会得到Nothing 确实,解决这个问题需要知道fail 何时返回底部,这很棘手。我仍然希望[ f x | Just x &lt;- list ] 和等效的do Just x &lt;- list ; return (f x) 不触发警告。不知道如何才能真正实现这一目标...... 我建议您为 -fwarn-implicit-fail 或类似的文件提交 GHC 功能请求,当脱糖插入对 fail 的调用时发出警告,而该调用不在源中。 我认为期望是当您以这种方式使用&lt;- 时,您知道自己在做什么,并且接受fail 可能会被调用。毕竟,您只能指定一个模式,因此您应该知道该模式是否详尽。这也是一个非常方便的功能 - 仅Just ... &lt;- 模式在 Hackage 中就出现了数百次。看到将其添加到 GHC 时进行的原始讨论会很有趣 - 我相信利弊已被广泛讨论。 ghc.haskell.org/trac/ghc/ticket/5813 "为失败的模式匹配提供编译器警告" 【参考方案1】:

就目前而言,为了避免这种怪癖导致的错误,您唯一能做的就是避免使用 MonadFail 实例的 monad(在最近的 GHC 版本中,不完整的绑定模式会导致编译错误)。

There is already an issue for this。还有一个声明为这个解决方案辩护,指出它可能是完全可取的,因此不值得警告:

这实际上是正确有用的行为。使用类似的东西

do
  Just x <- xs
  Just y <- ys
  return (x,y)

会做正确的事,如果 xs 或 ysresults 为 Nothing,则失败。为了 例如,在 list monad 中,它将创建 两个列表的非 Nothing 成员。解析单子可以回溯和 尝试另一条路线,IO monad 将创建一个有用的(和 确定性/可捕获)异常指向确切的文件和行 模式匹配的编号。 do 符号是唯一的地方 haskell 允许我们挂钩到模式匹配机制 通用的语言。

【讨论】:

以上是关于如何让 GHC 对 do 块中的不完整模式绑定发出警告?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 DO 块中执行选择查询?

在 Opensuse 42.3 上为 haskell 堆栈设置 ghc-8.2.1 时出现 ghc 完整性检查错误

异常块中的事务 - 如何?

Intero总是安装隔离的GHC

如何让 GHCi 加载 Opengl 包?

更改使用模式匹配来应用绑定运算符的do表达式