2009-12-30 17 views
73

¿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

+1

//, ¿No es esto una cuestión de opinión, sin embargo? –

Respuesta

88

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 y where 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 conexiones where que let. Demasiados let-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 y Either tipos.

  • Nunca escriba if <expression> then True else False; la frase correcta es simplemente <expression>.

  • No utilice head o tail 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 y short_name con guiones bajos para los locales where -bound o let las variables -bound.

+3

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

+2

@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. –

+0

^¿Incluso la perdición de Liskell? –

6

Sugiero echar un vistazo a este style checker.

+8

Y HLint http://hackage.haskell.org/package/hlint –

6
  • 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í

26

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, entonces join lo hace, entre otras cosas.
  • 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.
  • 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 estilo Applicative con ZipList 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 de Functor).
  • 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 como join :: Monad m => m (m a) -> m a. Hay menos margen de error al programar join porque al programar concat puede invertir las listas por error y en join hay muy pocas cosas que puede hacer.
  • 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 como ZipList.
4

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

Cuestiones relacionadas