gaw*_*awi 24 warnings haskell coding-style compiler-warnings ghc
使用GHC警告被视为良好做法-Wall
.但是,我发现修复这些警告会对某些类型的代码构造产生负面影响.
例1:
f >>
如果我没有明确使用_ <- f
表单,使用等号的do- not会产生警告:
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
Run Code Online (Sandbox Code Playgroud)
我明白我可以忘记做一些事情f
.但是,忽略结果是合理的(在解析器中很常见).使用时没有警告>>
,对吧?使用_ <-
比它应该更重.
例2:
使用可见函数的相同名称命名模式变量将给出:
Warning: This binding for `map' shadows the existing binding
imported from Prelude
Run Code Online (Sandbox Code Playgroud)
当使用记录语法时,这会越来越严重,因为命名空间会被快速污染.解决方案是在模式表达式中提供备用名称.因此,为了避免警告,我最终使用了一个不太合适的名称.我觉得这不是一个足够好的理由.
我知道我可以使用-fno-warn-...
选项,但我应该坚持使用-Wall
吗?
luq*_*qui 25
例1:
我已经重新学习了以Applicative样式编写解析器 - 它们更加简洁.例如,而不是:
funCallExpr :: Parser AST
funCallExpr = do
func <- atom
token "("
arg <- expr
token ")"
return $ FunCall func arg
Run Code Online (Sandbox Code Playgroud)
我反而写道:
funCallExpr :: Parser AST
funCallExpr = FunCall <$> atom <* token "(" <*> expr <* token ")"
Run Code Online (Sandbox Code Playgroud)
但是我可以说,如果你不喜欢这个警告,请按照它的建议禁用它.
例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
Run Code Online (Sandbox Code Playgroud)
另一个常见的惯例是添加匈牙利语前缀来记录标签:
data Foo = Foo { fooBaz :: Int, fooBar :: String }
Run Code Online (Sandbox Code Playgroud)
但是,在Haskell中使用记录并不好玩.无论如何,保持你的模块小,你的抽象紧,这应该不是问题.将它视为一种警告,即简化,男人.
sas*_*nin 10
我认为使用-Wall
可能导致代码不太可读.特别是,如果它正在做一些算术.
其他一些例子,其中使用-Wall
暗示修改具有更差的可读性.
(^)
有-Wall
需要的指数型签名考虑以下代码:
norm2 x y = sqrt (x^2 + y^2)
main = print $ norm2 1 1
Run Code Online (Sandbox Code Playgroud)
-Wall
它带有两个这样的警告:
rt.hs:1:18:
Warning: Defaulting the following constraint(s) to type `Integer'
`Integral t' arising from a use of `^' at rt.hs:2:18-20
In the first argument of `(+)', namely `x ^ 2'
In the first argument of `sqrt', namely `(x ^ 2 + y ^ 2)'
In the expression: sqrt (x ^ 2 + y ^ 2)
Run Code Online (Sandbox Code Playgroud)
(^(2::Int)
到处写,而(^2)
不是很好.
在编写快速而脏的代码时,这很烦人.对于简单代码,其中最多使用一种或两种数据类型(例如,我知道我只使用Double
s),在任何地方写入类型签名都可能使读取变得复杂.在上面的例子中,只有两个警告只是缺少类型签名:
rt.hs:1:0:
Warning: Definition but no type signature for `norm2'
Inferred type: norm2 :: forall a. (Floating a) => a -> a -> a
...
rt.hs:2:15:
Warning: Defaulting the following constraint(s) to type `Double'
`Floating a' arising from a use of `norm2' at rt.hs:2:15-23
In the second argument of `($)', namely `norm2 1 1'
In the expression: print $ norm2 1 1
In the definition of `main': main = print $ norm2 1 1
Run Code Online (Sandbox Code Playgroud)
作为分心,其中一个是指与需要类型签名的行不同的行.
Integral
是必要的这是第一个问题的一般情况.考虑一个例子:
stripe x = fromIntegral . round $ x - (fromIntegral (floor x))
main = mapM_ (print . stripe) [0,0.1..2.0]
Run Code Online (Sandbox Code Playgroud)
它给出了一堆警告.无处不fromIntegral
在转换回Double
:
rt2.hs:1:11:
Warning: Defaulting the following constraint(s) to type `Integer'
`Integral b' arising from a use of `fromIntegral' at rt2.hs:1:11-22
In the first argument of `(.)', namely `fromIntegral'
In the first argument of `($)', namely `fromIntegral . round'
In the expression:
fromIntegral . round $ x - (fromIntegral (floor x))
Run Code Online (Sandbox Code Playgroud)
每个人都知道fromIntegral
Haskell 需要多久一次......
有更多这样的情况,数字代码风险只是为了满足-Wall
要求而变得不可读.但我仍然使用-Wall
我想确定的代码.
小智 7
我建议继续使用'-Wall'作为默认选项,并使用相关文件顶部的OPTIONS_GHC编译指示,在本地,每个模块的基础上禁用所需的任何检查.
我可能会例外的是'-fno-warn-unused-do-bind',但有一个建议可能是使用一个明确的'void'函数...写'void f'似乎比'_ <更好- F'.
至于名称阴影 - 我认为如果可以的话,通常很好避免 - 在某些代码中间看到"map"会导致大多数Haskeller期望标准库fn.
名称阴影可能非常危险.特别是,很难推断出引入名称的范围.
在符号中使用未使用的模式并不是那么糟糕,但可以表明使用了比必要的效率低的功能(例如,mapM
代替mapM_
).
正如BenMos指出的那样,使用void
或ignore
明确地丢弃未使用的值是明确事物的好方法.
能够仅为一段代码禁用警告,而不是一次性禁用所有内容,这将是非常好的.此外,cabal标志和命令行ghc标志优先于文件中的标志,因此我不能在任何地方默认使用-Wall,甚至可以轻松地为整个单个文件禁用它.
归档时间: |
|
查看次数: |
3938 次 |
最近记录: |