Dobre standardy kodowania Haskell

Mógłby ktoś podać link do dobrego standardu kodowania dla Haskell? Znalazłem to i to , ale są one dalekie od kompleksowości. Nie wspominając już o tym, że HaskellWiki zawiera takie " klejnoty "jak" używaj klas z ostrożnością "i" definiowanie symbolicznych identyfikatorów infiksu powinno być pozostawione tylko pisarzom biblioteki."

Author: Alexey Romanov, 2009-12-31

5 answers

Naprawdę trudne pytanie. Mam nadzieję, że Twoje odpowiedzi przyniosą coś dobrego. Tymczasem oto katalog błędów lub innych irytujących rzeczy, które znalazłem w kodzie początkujących. Na stronę Cal tech style zwraca uwagę Kornel Kisielewicz. Niektóre z moich rad są tak niejasne i bezużyteczne jak "klejnoty" HaskellWiki, ale mam nadzieję, że przynajmniej jest to lepsza Rada: -) {]}

  • Sformatuj kod tak, aby pasował do 80 kolumn. (Zaawansowani użytkownicy mogą preferować 87 lub 88; poza tym jest popychanie go.)

  • Nie zapominaj, że let powiązania i where klauzule tworzą wzajemnie rekurencyjne Gniazdo definicji, nie a Sekwencja definicji.

  • Skorzystaj z klauzul where, zwłaszcza z ich zdolności do widzenia parametrów funkcji, które są już w zasięgu (miła, niejasna Rada). Jeśli jesteś naprawdę grokking Haskell, Twój kod powinien mieć o wiele więcej where - bindings niż let - bindings. Za dużo let-wiązań jest znak niezrealizowanego programisty ML lub Lispa.

  • Unikaj zbędnych nawiasów. Niektóre miejsca, w których zbędne nawiasy są szczególnie obraźliwe, to

    • W przeciwieństwie do innych języków programowania, nie można używać języka C.]}

    • Wokół aplikacji funkcji, która sama w sobie jest argumentem operatora infiksu (Aplikacja funkcji wiąże się mocniej niż jakikolwiek operator infiksu . Ten fakt powinien zostać spalony w mózgu każdego Haskellera, w taki sam sposób, jak w przypadku dinozaurów z USA, gdzie została spalona zasada skanowania od prawej do lewej.)

  • Umieść spacje wokół operatorów infiksu. Umieść spację po każdym przecinku w krotce literalnej.

  • Preferuje przestrzeń między funkcją a jej argumentem, nawet jeśli argument jest nawiasowy.

  • Użyj operatora $ rozsądnie, aby zmniejszyć nawiasy. Bądź świadomy bliskiego związku pomiędzy $ a infiksem .:

    f $ g $ h x == (f . g . h) x == f . g . h $ x
    
  • Nie przeocz wbudowanych typów Maybe i Either.

  • Nigdy nie pisz if <expression> then True else False; poprawna fraza to po prostu <expression>.

  • Nie używaj head lub tail, gdy możesz użyć dopasowania wzorca.

  • Nie przeocz kompozycji funkcji za pomocą operatora kropki infiksowej.

  • Ostrożnie używaj przerw linii. Podziały linii mogą zwiększyć czytelność, ale jest kompromis: Twój edytor może wyświetlać tylko 40-50 linii na raz. Jeśli chcesz przeczytać i zrozumieć dużą funkcję na raz, nie możesz nadużywać podziałów linii.

  • Prawie zawsze preferuj komentarze --, które biegną do końca linii nad komentarzami {- ... -}. Komentarze mogą być odpowiednie dla dużych nagłówków-to wszystko.

  • Nadaje każdej funkcji najwyższego poziomu wyraźny podpis typu.

  • Jeśli to możliwe, wyrównaj -- linie, = znaki, a nawet nawiasy i przecinki występujące w sąsiednich wierszach.

  • Pod wpływem GHC central preferuję użycie camelCase dla eksportowanych identyfikatorów i short_name z podkreślnikami dla lokalnych zmiennych where-bound lub let-bound.

 88
Author: Norman Ramsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-18 13:58:48

Kilka dobrych zasad kciuków imho:

  • skonsultuj się z HLint aby upewnić się, że nie masz zbędnych aparatów ortodontycznych i że Twój kod nie jest bezsensowny.
  • unikaj odtwarzania istniejących funkcji bibliotecznych. Hoogle pomoże Ci je znaleźć.
    • często istniejące funkcje biblioteczne są bardziej ogólne niż to, co zamierzano stworzyć. Na przykład, jeśli chcesz Maybe (Maybe a) -> Maybe a, to join robi to między innymi.
  • Argument nazewnictwo i dokumentacja są czasami ważne.
    • dla funkcji takiej jak replicate :: Int -> a -> [a], jest dość oczywiste, co robi każdy z argumentów, z samych ich typów.
    • dla funkcji, która pobiera kilka argumentów tego samego typu, np. isPrefixOf :: (Eq a) => [a] -> [a] -> Bool, nazewnictwo / dokumentacja argumentów jest ważniejsza.
  • Jeśli jedna funkcja istnieje tylko po to, aby służyć innej funkcji, a poza tym nie jest przydatna i / lub trudno wymyślić dla niej dobrą nazwę, to prawdopodobnie powinna istnieć w to klauzula where rozmówcy, a nie Zakres modułu.
  • suche
    • Użyj szablonu-Haskell, gdy jest to właściwe.
    • pakiety funkcji takich jak zip3, zipWith3, zip4, zipWith4, itp są bardzo meh. Zamiast tego użyj stylu Applicative z ZipLists. Prawdopodobnie nigdy nie potrzebujesz takich funkcji.
    • wywołaj instancje automatycznie. Pakiet derive może pomóc w wyprowadzaniu instancji klas typu, takich jak Functor (jest tylko jeden poprawny sposób, aby Typ był instancja Functor).
  • Kod bardziej ogólny ma kilka zalet:
      Jest bardziej użyteczny i nadaje się do wielokrotnego użytku.
  • jest mniej podatny na błędy, ponieważ jest więcej ograniczeń.
    • na przykład, jeśli chcesz zaprogramować concat :: [[a]] -> [a], i zauważ, jak może to być bardziej ogólne jako join :: Monad m => m (m a) -> m a. Jest mniej miejsca na błędy podczas programowania join, ponieważ podczas programowania concat Możesz przez pomyłkę odwrócić listę, a w join jest bardzo niewiele rzeczy, które możesz zrób.
  • gdy używasz tego samego stosu transformatorów monad w wielu miejscach kodu, utwórz dla niego synonim typu. Dzięki temu typy będą krótsze, bardziej zwięzłe i łatwiejsze do modyfikacji zbiorczej.
  • uważaj na "leniwe IO". Na przykład readFile tak naprawdę nie odczytuje zawartości pliku w momencie jego odczytu.
  • unikaj wcięcia tak bardzo, że nie mogę znaleźć kodu.
  • Jeśli twój typ jest logicznie instancją klasy typu, uczyń go przykład.
    • instancja może zastąpić inne funkcje interfejsu, które możesz rozważyć, znanymi.
    • Uwaga: Jeśli istnieje więcej niż jedna instancja logiczna, utwórz dla tych instancji wrappery typu newtype.
    • spraw, aby poszczególne instancje były spójne. Byłoby bardzo mylące / złe, gdyby lista Applicative zachowywała się jak ZipList.
  •  26
    Author: yairchu,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2011-10-18 01:17:49

    Proponuję rzucić okiem na ten style checker .

     6
    Author: Kornel Kisielewicz,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2009-12-30 23:28:03
    • Lubię próbować organizować funkcje jako kompozycje w stylu wolnym od punktów jak jak najbardziej poprzez robienie rzeczy like:

      func = boo . boppity . bippity . snd
          where boo = ...
                boppity = ...
                bippity = ...
      
    • Lubię używać ( $ ) tylko, aby uniknąć zagnieżdżonych parenów lub długich wyrażeń

    • ... Myślałem, że mam jeszcze kilka w sobie, no cóż

     6
    Author: jberryman,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2009-12-31 20:51:05

    Znalazłem dobry plik markdown obejmujący prawie każdy aspekt stylu kodu haskell. Może być używany jako Ściągawka. Znajdziesz go tutaj: link

     4
    Author: d12frosted,
    Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
    2013-12-26 10:53:57