Impacto en el estilo de GHC-Wall
Se considera una buena práctica habilitar las advertencias GHC con -Wall
. Sin embargo, he descubierto que corregir esas advertencias tiene un efecto negativo para algunos tipos de construcciones de código.
Ejemplo 1:
Usar el equivalente de do-notation de f >>
generará una advertencia si no uso explícitamente la forma _ <- 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
Entiendo que puedo olvidar hacer algo con el resultado de f
. Sin embargo, es legítimo ignorar el resultado (muy común en analizador). No hay advertencia cuando se usa >>
, ¿verdad? Usar _ <-
es más pesado de lo que debería.
Ejemplo 2:
Nombrar una variable de patrón con el mismo nombre de una función visible dará:
Warning: This binding for `map' shadows the existing binding
imported from Prelude
Esto está empeorando cuando se usa la sintaxis del registro, ya que el espacio de nombres se contamina rápidamente. La solución es dar un nombre alternativo en la expresión del patrón. Así que termino usando un nombre menos apropiado solo para evitar una advertencia. No siento que sea un razón suficiente.
Sé que puedo usar las opciones -fno-warn-...
, pero ¿debo seguir con -Wall
después de todo?
6 answers
Ejemplo 1:
He re-aprendido a escribir analizadores en estilo Aplicativo are son mucho más concisos. Por ejemplo, en lugar de:
funCallExpr :: Parser AST
funCallExpr = do
func <- atom
token "("
arg <- expr
token ")"
return $ FunCall func arg
En su lugar escribo:
funCallExpr :: Parser AST
funCallExpr = FunCall <$> atom <* token "(" <*> expr <* token ")"
Pero qué puedo decir, si no te gusta la advertencia, deshabilítala como sugiere.
Ejemplo 2:
Sí, encuentro esa advertencia un poco irritante también. Pero me ha salvado un par de veces.
Se vincula con las convenciones de nomenclatura. Me gusta mantener los módulos bastante pequeños, y mantener la mayoría de las importaciones cualificadas (excepto para las importaciones de "notación" como Control.Applicative
y Control.Arrow
). Eso mantiene bajas las posibilidades de conflicto de nombres, y solo hace que las cosas sean fáciles de trabajar. hothasktags
hace que este estilo sea tolerable si está utilizando etiquetas.
Si solo está coincidiendo con un patrón en un campo con el mismo nombre, puede usar -XNamedFieldPuns
o -XRecordWildCards
para reutilizar el nombre:
data Foo = Foo { baz :: Int, bar :: String }
-- RecordWildCards
doubleBaz :: Foo -> Int
doubleBaz (Foo {..}) = baz*baz
-- NamedFieldPuns
reverseBar :: Foo -> String
reverseBar (Foo {bar}) = reverse bar
Otra convención común es agregar un prefijo húngaro a los sellos discográficos:
data Foo = Foo { fooBaz :: Int, fooBar :: String }
Pero sí, los registros no son divertidos para trabaja con Haskell. De todos modos, mantenga sus módulos pequeños y sus abstracciones apretadas y esto no debería ser un problema. Considéralo como una advertencia que dice simplifyyyy, hombre .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-28 10:05:38
Creo que el uso de -Wall
puede conducir a un código menos legible. Especialmente, si está haciendo algo de aritmética.
Algunos otros ejemplos, donde el uso de -Wall
sugiere modificaciones con peor legibilidad.
(^)
con -Wall
requiere firmas de tipo para exponentes
Considere este código:
norm2 x y = sqrt (x^2 + y^2)
main = print $ norm2 1 1
Con -Wall
da dos advertencias como esta:
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)
Escribir (^(2::Int)
en todas partes en lugar de (^2)
no es agradable.
Las firmas de tipo son requerido para todos los niveles superiores
Al escribir código rápido y sucio, es molesto. Para código simple, donde hay como máximo uno o dos tipos de datos en uso (para exapmle, sé que solo trabajo con Double
s), escribir firmas de tipo en todas partes puede complicar la lectura. En el ejemplo anterior hay dos advertencias solo por la falta de firma de tipo:
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
Como distracción, uno de ellos se refiere a la línea diferente de la que es la firma de tipo necesario.
Las firmas de tipo para los cálculos intermedios con Integral
son necesarias
Este es un caso general del primer problema. Considere un ejemplo:
stripe x = fromIntegral . round $ x - (fromIntegral (floor x))
main = mapM_ (print . stripe) [0,0.1..2.0]
Da un montón de advertencias. En todas partes con fromIntegral
para convertir de nuevo a 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))
Y todo el mundo sabe con qué frecuencia se necesita fromIntegral
en Haskell...
Hay más casos como estos el código numérico corre el riesgo de ser ilegible solo para cumplir con los requisitos -Wall
. Pero yo sigue usando -Wall
en el código del que me gustaría estar seguro.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-15 12:12:05
Recomendaría continuar usando '-Wall' como la opción por defecto, y deshabilitar cualquier comprobación que necesite en base local, por módulo usando un pragma OPTIONS_GHC en la parte superior de los archivos relevantes.
El que podría hacer una excepción es de hecho '-fno-warn-unused-do-bind', pero una sugerencia podría ser usar una función 'void' explícita ... escribir 'void f' parece más bonito que '_
En cuanto al sombreado de nombres-creo que generalmente es bueno evitar si puede - ver 'mapa' en el middle of some code llevará a la mayoría de los Haskelers a esperar la biblioteca estándar fn.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-14 07:22:10
El sombreado de nombres puede ser bastante peligroso. En particular, puede ser difícil razonar sobre en qué ámbito se introduce un nombre.
Los enlaces de patrones no utilizados en notación do no son tan malos, pero pueden indicar que se está utilizando una función menos eficiente de la necesaria (por ejemplo, mapM
en lugar de mapM_
).
Como señaló BenMos, usar void
o ignore
para descartar explícitamente los valores no utilizados es una buena manera de ser explícito sobre las cosas.
Sería muy bueno poder desactivar advertencias para solo una sección de código, en lugar de para todo a la vez. Además, las banderas cabal y las banderas ghc de la línea de comandos tienen prioridad sobre las banderas en un archivo, por lo que no puedo tener-Wall por defecto en todas partes e incluso simplemente deshabilitarlo para la totalidad de un solo archivo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-25 16:43:36
También existe la opción mucho menos intrusiva -W
, que habilita un conjunto de advertencias razonables relacionadas principalmente con el estilo de codificación general (importaciones no utilizadas, variables no utilizadas, coincidencias de patrones incompletas, etc.).
En particular, no incluye las dos advertencias que usted mencionó.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-04 05:33:41
Todas estas advertencias ayudan a prevenir errores y deben ser respetadas, no suprimidas. Si desea definir una función con un nombre de Prelude, puede ocultarla utilizando
Import Prelude hiding (map)
La sintaxis'Hiding' solo debe usarse para Prelude y módulos del mismo paquete, de lo contrario se corre el riesgo de que se rompa el código por cambios en la API del módulo importado.
Véase: http://www.haskell.org/haskellwiki/Import_modules_properly
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-21 17:42:26