使用 -Wall
启用 GHC 警告被认为是良好的做法。 。但是,我发现修复这些警告会对某些类型的代码构造产生负面影响。
示例 1:
使用相当于f >>
的do符号如果我没有明确使用 _ <- f
将生成警告形式:
Warning: A do-notation statement discarded a result of type Char.
Suppress this warning by saying "_ <- f",
or by using the flag -fno-warn-unused-do-bind
我知道我可能会忘记对 f
的结果执行某些操作。然而,忽略结果是合法的(在解析器中很常见)。使用>>
时没有任何警告, 正确的?使用_ <-
比应有的重。
示例 2:
使用与可见函数相同的名称命名模式变量将给出:
Warning: This binding for `map' shadows the existing binding
imported from Prelude
当使用记录语法时,情况会变得更糟,因为 namespace 很快就会被污染。解决方案是在模式表达式中给出一个备用名称。所以我最终使用了一个不太合适的名称以避免警告。我觉得这个理由不够充分。
我知道我可以使用-fno-warn-...
选项,但我应该坚持 -Wall
毕竟?
最佳答案
示例 1:
我重新学习了以应用风格编写解析器——它们更加简洁。例如,而不是:
funCallExpr :: Parser AST
funCallExpr = do
func <- atom
token "("
arg <- expr
token ")"
return $ FunCall func arg
我改为写:
funCallExpr :: Parser AST
funCallExpr = FunCall <$> atom <* token "(" <*> expr <* token ")"
但是我能说什么,如果您不喜欢这个警告,请按照它的建议禁用它。
示例 2:
是的,我发现这个警告也有点令人恼火。但它救了我几次。
它与命名约定相关。我喜欢保持模块非常小,并保持大多数导入合格(除了像 Control.Applicative
和 Control.Arrow
这样的“符号”导入)。这样可以降低名称冲突的可能性,并且使工作变得更容易。如果您使用标签,hothasktags
使这种样式可以接受。
如果您只是对同名字段进行模式匹配,则可以使用 -XNamedFieldPuns
或 -XRecordWildCards
来重用该名称:
data Foo = Foo { baz :: Int, bar :: String }
-- RecordWildCards
doubleBaz :: Foo -> Int
doubleBaz (Foo {..}) = baz*baz
-- NamedFieldPuns
reverseBar :: Foo -> String
reverseBar (Foo {bar}) = reverse bar
另一个常见的约定是在记录标签中添加匈牙利语前缀:
data Foo = Foo { fooBaz :: Int, fooBar :: String }
但是,是的,在 Haskell 中使用记录并不有趣。不管怎样,保持你的模块小并且你的抽象紧密,这应该不是问题。将其视为一个警告,表示simplifyyyy,伙计。
关于haskell - 对 GHC -Wall 风格的影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4174629/