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