Qualcuno potrebbe fornire un collegamento ad un buon standard di codifica per Haskell? Ho trovato this e this, ma sono tutt'altro che comprensivi. Per non parlare del fatto che HaskellWiki include "gemme" come "usa le classi con cura" e "la definizione degli identificatori di simboli simbolici deve essere lasciata solo agli scrittori di librerie".Buone norme di codifica Haskell
risposta
Davvero una domanda difficile. Spero che le tue risposte presentino qualcosa di buono. Nel frattempo, ecco un catalogo di errori o altre cose fastidiose che ho trovato nel codice dei principianti. C'è una certa sovrapposizione con la pagina di stile Cal Tech a cui Kornel Kisielewicz punta. Alcuni dei miei consigli è altrettanto vago e inutile come le "chicche" HaskellWiki, ma spero almeno è meglio consigli :-)
Formato il codice in modo che si adatta in 80 colonne. (Gli utenti più esperti potrebbero preferire 87 o 88, al di là che sta spingendo esso.)
Non dimenticate che
let
attacchi ewhere
clausole di creare un nido reciprocamente ricorsivo di definizioni, non una sequenza di di definizioni.Sfruttare le clausole
where
, in particolare la loro capacità di visualizzare i parametri di funzione già in ambito (consigli vaghi e carini). Se sei veramente grok Haskell, il tuo codice dovrebbe avere molto piùwhere
-legamenti dilet
-bindings. Troppilet
-bindings sono un segno di un programmatore ML o programmatore Lisp non ricostruito.Evitare parentesi ridondanti. Alcuni luoghi dove parentesi ridondanti sono particolarmente offensive sono
Intorno la condizione in un
if
espressione (marche voi come un programmatore C irriducibile)Circa un'applicazione funzione che è di per sé l'argomento di un operatore infisso (applicazione funzione si lega più stretto rispetto a qualsiasi operatore infisso. Questo fatto dovrebbe essere bruciato nel cervello di ogni Haskeller, più o meno allo stesso modo in cui noi dinosauri avevano di APL da destra a sinistra regola scansione bruciato in.)
Mettere gli spazi attorno agli operatori infissi. Metti uno spazio seguendo ogni virgola in una letterale di tupla.
Preferire uno spazio tra una funzione e il relativo argomento, anche se l'argomento è tra parentesi.
Utilizzare l'operatore
$
per ridurre le parentesi. Essere consapevoli della stretta relazione tra$
e infisso.
:f $ g $ h x == (f . g . h) x == f . g . h $ x
non trascurare il built-in
Maybe
eEither
tipi.Mai scrivere
if <expression> then True else False
; la frase corretta è semplicemente<expression>
.Non utilizzare
head
otail
quando è possibile utilizzare la corrispondenza del modello.Non trascurare la composizione delle funzioni con l'operatore punto infisso.
Utilizzare le interruzioni di riga con attenzione. Le interruzioni di riga possono aumentare la leggibilità, ma c'è un compromesso: il tuo editor può visualizzare solo 40-50 linee alla volta. Se hai bisogno di leggere e capire una grande funzione tutto in una volta, non devi abusare delle interruzioni di linea.
Quasi sempre preferiscono i commenti
--
che vengono eseguiti fino alla fine della riga sui commenti{- ... -}
. I commenti rinforzati potrebbero essere appropriati per le intestazioni di grandi dimensioni —.Assegnare a ciascuna funzione di livello superiore una firma di tipo esplicita.
Quando possibile, allineare
--
linee,=
segni e perfino parentesi e virgole che si verificano nelle linee adiacenti.influenzate come sono dalla GHC centrale, ho una preferenza molto mite da utilizzare per gli identificatori
camelCase
esportati eshort_name
di sottolineatura per localiwhere
-bound olet
variabili -bound.
Mi piace molto questa risposta, ma puoi fornire altri esempi di codice?Non ho ancora familiarità con il gergo di Haskell, quindi "l'applicazione della funzione è più stretta di qualsiasi altro operatore infisso" e alcuni altri punti mi lasciano confuso. – CaptainCasey
@CaptainCasey: ho iniziato ad aggiungere alcuni esempi, ma poi la risposta è diventata troppo lunga e difficile da leggere. È inteso come un breve insieme di suggerimenti; se deve trasformarsi in una vera guida di stile, dovrà essere fatto da qualcun altro. Ma fammi sapere i tuoi punti specifici. La tenuta vincolante significa semplicemente che '(lunghezza l) + 1' è brutto. L'applicazione di 'length' si lega automaticamente più strettamente dell'applicazione di +, quindi la cosa idiomatica da scrivere è' length l + 1'. Le parentesi sono la rovina dei programmi funzionali. –
^Anche la rovina di Liskell? –
Suggerirei di dare un'occhiata a questo style checker.
E HLint http://hackage.haskell.org/package/hlint –
mi piace cercare di organizzare le funzioni come composizioni stile libero-point come più possibile facendo le cose come:
func = boo . boppity . bippity . snd where boo = ... boppity = ... bippity = ...
Mi piace usare ($) solo per evitare parenti annidati o espressioni parentesi lunghe
... pensavo di averne ancora in me, oh ben
Alcune buone regole di pollice IMHO:
- Consultare HLint per assicurarsi che non si dispone di bretelle ridondanti e non che il codice è inutilmente punto pieno.
- Evitare di ricreare le funzioni di libreria esistenti. Hoogle può aiutarti a trovarli.
- Spesso le funzioni di libreria esistenti sono più generiche di quelle che si sarebbero verificate. Ad esempio se si desidera
Maybe (Maybe a) -> Maybe a
, quindi lojoin
lo fa tra le altre cose.
- Spesso le funzioni di libreria esistenti sono più generiche di quelle che si sarebbero verificate. Ad esempio se si desidera
- Talvolta la denominazione e la documentazione degli argomenti sono importanti.
- Per una funzione come
replicate :: Int -> a -> [a]
, è piuttosto ovvio ciò che ciascuno degli argomenti fa, dai loro tipi solo. - Per una funzione che richiede diversi argomenti dello stesso tipo, ad esempio
isPrefixOf :: (Eq a) => [a] -> [a] -> Bool
, la denominazione/documentazione degli argomenti è più importante.
- Per una funzione come
- Se una funzione esiste solo per servire un'altra funzione, e non è comunque utile, e/o è difficile pensare ad un buon nome per esso, allora probabilmente dovrebbe esistere nella sua
where
clausola del chiamante invece che in l'ambito del modulo. - DRY
- Usa modello-Haskell, quando opportuno.
- I pacchetti di funzioni come
zip3
,zipWith3
,zip4
,zipWith4
, ecc. Sono molto meh. Utilizzare invece lo stileApplicative
conZipList
s. Probabilmente non hai mai veramente bisogno di funzioni come quelle. - Ricava automaticamente le istanze. Il pacchetto derive può aiutare a ricavare istanze per classi di tipo come
Functor
(esiste un solo modo corretto per rendere un tipo un'istanza diFunctor
).
- codice che è più generale ha diversi vantaggi:
- E 'più utile e riutilizzabile.
- È meno soggetto a bug perché ci sono più vincoli.
- Ad esempio se si desidera programmare
concat :: [[a]] -> [a]
e notare come può essere più generale comejoin :: Monad m => m (m a) -> m a
. C'è meno spazio per errori quando si programma perché durante la programmazione diconcat
è possibile invertire gli elenchi per errore e injoin
ci sono pochissime cose che si possono fare.
- Ad esempio se si desidera programmare
- Quando si utilizza lo stesso stack di trasformatori monade in molti luoghi nel codice, fare un tipo sinonimo di esso. Ciò renderà i tipi più brevi, più concisi e più facili da modificare alla rinfusa.
- Attenzione a "IO pigro". Ad esempio,
readFile
non legge realmente il contenuto del file nel momento in cui il file viene letto. - Evita di indentare così tanto che non riesco a trovare il codice.
- Se il proprio tipo è logicamente un'istanza di una classe di tipo, trasformarlo in un'istanza.
- L'istanza può sostituire altre funzioni dell'interfaccia che è possibile considerare con quelle familiari.
- Nota: se è presente più di un'istanza logica, creare newtype-wrappers per le istanze.
- Rende coerenti le diverse istanze. Sarebbe stato molto confuso/cattivo se la lista
Applicative
si comportava comeZipList
.
ho trovato buon file Markdown che copre quasi tutti gli aspetti dello stile di codice Haskell. Può essere usato come un cheat sheet. Potete trovarlo qui: link
- 1. Codifica SHA1 in Haskell
- 2. Buone librerie di suoni?
- 3. Concurrent Dizionario Utilizzo a norme
- 4. Perché le norme spesso vengono chiuse?
- 5. buone pratiche di Makefile
- 6. chiamata set di regole e norme comuni FluentValidation
- 7. Strumenti e norme per il documento di progettazione tecnica
- 8. JavaScript di codifica Esempi
- 9. Sta usando le buone pratiche cfsqltype?
- 10. Buone librerie matematiche per haskell come pylab e scipy per python?
- 11. Buone librerie PHP autorizza.net
- 12. Buone guide multithreading?
- 13. Buone implementazioni dell'apprendimento rinforzato?
- 14. Buone pratiche: JDBC Connection
- 15. Vincoli di correttezza della codifica direttamente nel sistema di tipi Haskell?
- 16. Implementazioni di indici spaziali in Haskell?
- 17. Codifica Python 36 codifica
- 18. Database Upserts - Buone o cattive pratiche?
- 19. Torre di Hanoi - JavaScript - le parti buone
- 20. Buone pratiche dei cookie MVC di ASP.Net
- 21. Libri su buone pratiche di programmazione
- 22. Gerarchia di buone chiamate in Eclipse/PyDev
- 23. Buone risorse per l'apprendimento di PL/pgSQL?
- 24. Buone caratteristiche per un ORM
- 25. Buone Delphi Prism risorse online
- 26. Buone pratiche per multi-threading
- 27. Buone risorse per l'apprendimento WPF
- 28. Che cos'è una buona piattaforma (codifica) da utilizzare per l'intervista di codifica telefonica?
- 29. Buone risorse per imparare MacRuby
- 30. Linee guida per la codifica + Best practice?
//, Non è una questione di opinione, però? –