Хорошие стандарты кодирования Haskell



может ли кто-нибудь предоставить ссылку на хороший стандарт кодирования для Haskell? Я нашел этой и этой, но они далеко не полные. Не говоря уже о том, что HaskellWiki one включает в себя такие "драгоценные камни", как "использовать классы с осторожностью" и "определение идентификаторов символьных инфиксов должно быть оставлено только для авторов библиотек."

599   5  

5 ответов:

очень сложный вопрос. Я надеюсь, что ваши ответы окажутся чем-то хорошим. Между тем, вот каталог ошибок или других раздражающих вещей, которые я нашел в коде начинающих. Существует некоторое перекрытие со страницей стиля Cal Tech, на которую указывает Корнель Киселевич. Некоторые из моих советов так же расплывчаты и бесполезны, как "драгоценные камни" HaskellWiki, но я надеюсь, что по крайней мере это лучший совет :-)

  • отформатируйте свой код так, чтобы он помещался в 80 столбцов. (Продвинутые пользователи могут предпочитаю 87 или 88; дальше этого толкает его.)

  • не забывай об этом let далее where предложения создают взаимно рекурсивное гнездо определений,не a последовательность определений.

  • воспользоваться where предложения, особенно их способность видеть параметры функции, которые уже находятся в области действия (хороший неопределенный совет). Если вы действительно grokking Haskell, ваш код должен иметь намного больше where-Привязок, чем let-Привязок. Слишком много let - привязки-это признак нереконструированного программиста ML или программиста Lisp.

  • избегайте избыточных скобок. Некоторые места, где избыточные скобки особенно оскорбительны

    • по состоянию на if выражение (клеймит вас как нереконструированный программист C)

    • вокруг приложения функции, которое само по себе является аргумент инфиксного оператора (функция приложения связывается крепче, чем любой оператор инфикса. Этот факт должен быть выжжен в мозгу каждого Хаскеллера, во многом так же, как у нас, динозавров, было правило сканирования справа налево APL.)

  • поместите пробелы вокруг операторов инфикса. Поставьте пробел после каждой запятой в литерале кортежа.

  • предпочитаю пространство между функцией и ее аргументом, Даже если аргумент заключен в скобки.

  • использовать $ оператор рассудительно урезал скобки. Будьте в курсе тесной связи между $ и инфиксной .:

    f $ g $ h x == (f . g . h) x == f . g . h $ x
    
  • не пропустите встроенный Maybe и Either типы.

  • никогда не пишу if <expression> then True else False; правильная фраза просто <expression>.

  • не используйте head или tail когда вы могли бы использовать сопоставление по образцу.

  • не упускайте из виду композицию функций с помощью оператора infix dot.

  • осторожно используйте разрывы строк. Разрывы строк могут увеличить читаемость, но есть компромисс: ваш редактор может отображать только 40-50 строк сразу. Если вам нужно прочитать и понять большую функцию сразу, вы не должны злоупотреблять разрывами строк.

  • почти всегда предпочитают -- комментарии, которые идут до конца строки через {- ... -} комментарии. Связанные комментарии могут быть подходящими для больших заголовков-вот и все.

  • дайте каждой функции верхнего уровня явную сигнатуру типа.

  • по возможности выровняйте -- линии, = знаки и даже круглые скобки и запятые, которые встречаются в соседних строках.

  • под влиянием, как я на GHC central, у меня есть очень мягкий предпочтение использовать camelCase для экспортируемых идентификаторов и short_name с подчеркиванием для локального whereили let-связанные переменные.

некоторые хорошие правила больших пальцев имхо:

  • проконсультируйтесь с HLint чтобы убедиться, что у вас нет избыточных фигурных скобок и что ваш код не бессмысленно точечный.
  • избегайте повторного создания существующих библиотечных функций. Hoogle могу помочь вам найти их.
    • часто существующие библиотечные функции являются более общими, чем то, что вы собирались сделать. Например, если вы хотите Maybe (Maybe a) -> Maybe a, потом join Это среди других вещи.
  • иногда важны имена аргументов и документация.
    • функции как replicate :: Int -> a -> [a], это довольно очевидно, что каждый из аргументов нет, только от их типов.
    • для функции, которая принимает несколько аргументов одного типа, например isPrefixOf :: (Eq a) => [a] -> [a] -> Bool, именование / документирование аргументов является более важным.
  • если одна функция существует только для обслуживания другой функции, а не иначе полезно, и/или трудно придумать хорошее название для него, то он, вероятно, должен существовать в его абонента where предложение вместо в области модуля.
  • сухой
    • используйте шаблон-Haskell, когда это необходимо.
    • связки функций, таких как zip3,zipWith3,zip4,zipWith4 и т. д. Очень ниочень. Используйте Applicative стиль ZipLists вместо этого. Вам, вероятно, никогда не нужны такие функции.
    • производные экземпляры автоматически. Этот вывести пакет может помочь вам получить экземпляры для классов типа, таких как Functor (есть только один правильный способ сделать тип экземпляра Functor).
  • код, который является более общим, имеет ряд преимуществ:
    • это более полезно и многоразовые.
    • он менее склонен к ошибкам, потому что есть больше ограничений.
      • например, если вы хотите программу concat :: [[a]] -> [a], и обратите внимание, как это может быть более общим, как join :: Monad m => m (m a) -> m a. Там меньше места для ошибок при программировании join потому что при программировании concat вы можете изменить списки по ошибке и в join есть очень мало вещей, которые вы можете сделать.
  • при использовании одного и того же стека трансформаторов монад во многих местах вашего кода сделайте для него синоним типа. Это сделает типы более короткими, более краткими и более простыми для массового изменения.
  • остерегайтесь "ленивый IO". Например readFile на самом деле не читает содержимое файла в момент чтения файла.
  • не выделять так сильно, что я не могу найти код.
  • если ваш тип логически является экземпляром класса типа, сделайте его экземпляром.
    • экземпляр может заменить другие функции интерфейса, которые вы, возможно, рассматривали, на знакомые.
    • Примечание: если существует более одного логического экземпляра, создайте NewType-оболочки для экземпляров.
    • сделать другой экземпляры непротиворечивы. Было бы очень запутанно / плохо, если бы список Applicative вели себя как ZipList.

Я бы предложил взглянуть на это проверка стиль.

  • мне нравится пытаться организовать функции как точечные композиции стиля, как насколько это возможно, делая вещи например:

    func = boo . boppity . bippity . snd
        where boo = ...
              boppity = ...
              bippity = ...
    
  • мне нравится использовать ( $ ) только для того, чтобы избежать вложенных пар или длинных выражений в скобках

  • ... Я думал, что у меня есть еще несколько во мне, о хорошо

Я нашел хороший файл markdown, охватывающий почти все аспекты стиля кода haskell. Его можно использовать как шпаргалку. Вы можете найти его здесь: ссылке

Comments

    Ничего не найдено.