¿Podría alguien proporcionar un enlace a un buen estándar de codificación para Haskell? He encontrado this y this, pero están lejos de ser completo. Sin mencionar que el HaskellWiki incluye tales "gemas" como "usa las clases con cuidado" y "la definición de identificadores de infijo simbólicos solo debe dejarse a los escritores de la biblioteca".Buenas normas de codificación de Haskell
Respuesta
Pregunta realmente difícil. Espero que tus respuestas encuentren algo bueno. Mientras tanto, aquí hay un catálogo de errores u otras cosas molestas que he encontrado en el código para principiantes. Hay cierta superposición con la página de estilo de Cal Tech que Kornel Kisielewicz señala. Algunos de mi consejo es tan vaga e inútil como las "joyas" HaskellWiki, pero espero que al menos es mejor asesoramiento :-)
Formato su código para que se ajuste en 80 columnas. (Los usuarios avanzados pueden preferir 87 o 88, más allá de que lo está empujando.)
No olvide que
let
fijaciones ywhere
cláusulas crean un nido mutuamente recursivo de las definiciones, no una secuencia de de definiciones.Aproveche las cláusulas
where
, especialmente su capacidad para ver los parámetros de función que ya están en el alcance (consejos vagos). Si realmente estás compartiendo Haskell, tu código debería tener muchas más conexioneswhere
quelet
. Demasiadoslet
-enlaces es un signo de un programador de ML no reconstruido o programador Lisp.Evite paréntesis redundantes. Algunos lugares en los paréntesis redundantes son particularmente ofensivo son
Alrededor de la condición en una expresión
if
(le marcas como un programador de C no reconstruido)Alrededor de una aplicación de función que es en sí el argumento de un operador infijo (aplicación de función se une más fuerte que cualquier operador infijo. Este hecho debe ser grabada a fuego en el cerebro de cada Haskeller, casi de la misma manera que nosotros los dinosaurios tenían de APL-derecha-izquierda regla de exploración quemado en.)
Coloque espacios alrededor de operadores de infijo. Pon un espacio después de cada coma en un literal de tupla.
Prefiere un espacio entre una función y su argumento, incluso si el argumento está entre paréntesis.
Utilice el operador
$
con cuidado para reducir entre paréntesis. Sé consciente de la estrecha relación entre$
y infija.
:f $ g $ h x == (f . g . h) x == f . g . h $ x
No pase por alto la incorporada en
Maybe
yEither
tipos.Nunca escriba
if <expression> then True else False
; la frase correcta es simplemente<expression>
.No utilice
head
otail
si puede usar la coincidencia de patrones.No omita la composición de la función con el operador de punto infijo.
Use los saltos de línea con cuidado. Los saltos de línea pueden aumentar la legibilidad, pero hay una compensación: su editor puede mostrar solo 40-50 líneas a la vez. Si necesita leer y comprender una función grande al mismo tiempo, no debe abusar de los saltos de línea.
Casi siempre prefiero los comentarios
--
que se ejecutan al final de la línea sobre los comentarios{- ... -}
. Los comentarios arriostrados pueden ser apropiados para encabezados grandes — eso es todo.Proporcione a cada función de nivel superior una firma de tipo explícita.
Cuando sea posible, alinee las líneas
--
,=
, e incluso los paréntesis y las comas que aparecen en las líneas adyacentes.influenciada como estoy por el centro de GHC, que tienen una preferencia muy leves a utilizar
camelCase
para los identificadores exportados yshort_name
con guiones bajos para los localeswhere
-bound olet
las variables -bound.
Me gusta mucho esta respuesta, pero ¿puede proporcionar más ejemplos de código?Todavía no estoy completamente familiarizado con la jerga de Haskell, por lo que la "aplicación de función se une más estrecha que cualquier operador de infijo" y algunos otros puntos me dejan confundido. – CaptainCasey
@CaptainCasey: comencé a agregar algunos ejemplos, pero luego la respuesta se hizo demasiado larga y difícil de leer. Se entiende como un conjunto corto de sugerencias; si se trata de convertirse en una verdadera guía de estilo, tendrá que ser hecha por otra persona. Pero déjame saber tus puntos específicos. La rigidez de unión solo significa que '(longitud l) + 1' es feo. La aplicación de 'length' se une automáticamente más apretada que la aplicación de' + ', por lo que lo idiomático para escribir es' length l + 1'. Los paréntesis son la ruina de los programas funcionales. –
^¿Incluso la perdición de Liskell? –
Sugiero echar un vistazo a este style checker.
Y HLint http://hackage.haskell.org/package/hlint –
me gusta tratar de organizar funciones como composiciones de estilo libre de puntos como tanto como sea posible por hacer las cosas como:
func = boo . boppity . bippity . snd where boo = ... boppity = ... bippity = ...
me gusta usar ($) solamente para evitar parens anidados o expresiones entre paréntesis largas
... Pensé que tenía algunas más en mí, oh así
Algunas buenas reglas de los pulgares imho:
- Consulte con HLint para asegurarse de que usted no tiene apoyos redundantes y no es que su código es inútilmente punto completo.
- Evite volver a crear funciones de biblioteca existentes. Hoogle puede ayudarlo a encontrarlos.
- Muchas veces las funciones existentes de la biblioteca son más generales de lo que se iba a hacer. Por ejemplo, si quiere
Maybe (Maybe a) -> Maybe a
, entoncesjoin
lo hace, entre otras cosas.
- Muchas veces las funciones existentes de la biblioteca son más generales de lo que se iba a hacer. Por ejemplo, si quiere
- La denominación del argumento y la documentación son importantes a veces.
- Para una función como
replicate :: Int -> a -> [a]
, es bastante obvio lo que hace cada uno de los argumentos, solo de sus tipos. - Para una función que toma varios argumentos del mismo tipo, como
isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
, la asignación de nombres/documentación de argumentos es más importante.
- Para una función como
- Si una función existe sólo para servir a otra función y no es otra cosa útil, y/o que es difícil pensar en un buen nombre para él, entonces probablemente debería existir en él es la cláusula de la persona que llama
where
en lugar de en el alcance del módulo. - DRY
- Use Template-Haskell cuando corresponda.
- Paquetes de funciones como
zip3
,zipWith3
,zip4
,zipWith4
, etc. son muy meh. Utilice el estiloApplicative
conZipList
s en su lugar. Probablemente nunca necesites funciones como esas. - Derivar instancias automáticamente. El paquete derive puede ayudarlo a derivar instancias para clases de tipos como
Functor
(solo hay una forma correcta de hacer que un tipo sea una instancia deFunctor
).
- código que es más general tiene varias ventajas:
- Es más útil y reutilizable.
- Es menos propenso a errores porque hay más restricciones.
- Por ejemplo, si desea programar
concat :: [[a]] -> [a]
, y observe cómo puede ser más general comojoin :: Monad m => m (m a) -> m a
. Hay menos margen de error al programarjoin
porque al programarconcat
puede invertir las listas por error y enjoin
hay muy pocas cosas que puede hacer.
- Por ejemplo, si desea programar
- Cuando se utiliza la misma pila de transformadores monad en muchos lugares en su código, hacer un sinónimo de tipo para ello. Esto hará que los tipos sean más cortos, más concisos y más fáciles de modificar a granel.
- Tenga cuidado con "IO perezoso". Por ejemplo,
readFile
realmente no lee el contenido del archivo en el momento en que se lee el archivo. - Evite sangrar tanto que no pueda encontrar el código.
- Si su tipo es lógicamente una instancia de tipo-clase, conviértalo en una instancia.
- La instancia puede reemplazar otras funciones de interfaz que haya considerado con las familiares.
- Nota: Si hay más de una instancia lógica, cree newtype-wrappers para las instancias.
- Haga que las diferentes instancias sean coherentes. Hubiera sido muy confuso/malo si la lista
Applicative
se comportara comoZipList
.
me pareció buen archivo de reducción del precio que cubre casi todos los aspectos del estilo de código Haskell. Se puede usar como hoja de trucos. Puede encontrarlo aquí: link
- 1. Normas y buenas prácticas de codificación de Erlang
- 2. Codificación de Normas de estilo para Android
- 3. Normas de codificación de C# de Juval Lowy Preguntas
- 4. Codificación SHA1 en Haskell
- 5. Sugerencias de literatura sobre mejores prácticas/buenas técnicas de codificación
- 6. PHPStorm normas de inspección
- 7. ¿Existe una herramienta de cumplimiento de normas de codificación para Scala?
- 8. ¿Hay alguna sugerencia para desarrollar un documento de normas/mejores prácticas de codificación de C#?
- 9. ¿Buenas bibliotecas de sonido?
- 10. compatibilidad con normas g ++
- 11. Normas de código de salida en Python
- 12. IE8 navegador Mode & Normas modo
- 13. Buenas prácticas de NoSQL
- 14. Normas de conversión implícita de argumentos de plantilla
- 15. JavaScript ejemplos de codificación
- 16. ANSI C vs otras normas C
- 17. confusión en la comprensión C++ normas
- 18. Buenas prácticas de Webrequest asíncronas
- 19. moq - buenas aplicaciones de muestra
- 20. Buenas prácticas: JDBC de conexión
- 21. Buenas herramientas de métrica PHP
- 22. Buenas prácticas de Cruise Control.Net
- 23. patrón Repositorio de Buenas Prácticas
- 24. ¿Buenas formas de aprender cacao?
- 25. Buenas prácticas de transacciones NHibernate
- 26. CSS selectores de atributos: las normas sobre las cotizaciones
- 27. ¿Cuáles son las normas relativas encadenamiento de "==" y en Python
- 28. PHP 5 deshabilita el error de normas estrictas
- 29. diferencia entre las normas de Apache para bloquear libwww-perl
- 30. Estándares de codificación PHP
//, ¿No es esto una cuestión de opinión, sin embargo? –