Может ли кто-нибудь предоставить ссылку на хороший стандарт кодирования для Haskell? Я нашел этот и этот, но они далеки от всеобъемлющего. Не говоря уже о том, что HaskellWiki включает такие "драгоценные камни", как "классы использования с осторожностью" и "определение символических идентификаторов инфикс следует оставлять только библиотечным писателям".
Хорошие стандарты кодирования Haskell
Ответ 1
Действительно сложный вопрос. Надеюсь, ваши ответы будут полезными. Между тем, вот каталог ошибок или других раздражающих вещей, которые я нашел в коде для новичков. Некоторое совпадение с страницей стиля Cal Tech, на которую указывает Kornel Kisielewicz. Некоторые из моих советов кажутся расплывчатыми и бесполезными, как "драгоценные камни" HaskellWiki, но я надеюсь, что, по крайней мере, это лучший совет: -)
-
Отформатируйте свой код, чтобы он соответствовал 80 столбцам. (Продвинутые пользователи могут предпочесть 87 или 88, кроме того, что это толкает его.)
-
Не забывайте, что привязки
letиwhereсоздают взаимно-рекурсивное гнездо определений, а не последовательность определений. -
Воспользуйтесь предложениями
where, особенно их способностью видеть параметры функций, которые уже находятся в области видимости (славные смутные советы). Если вы действительно grokking Haskell, ваш код должен иметь гораздо большеwhere-связанных, чемlet-обязаний. Слишком многоlet-связок является признаком нереконструированного программиста ML или программиста Lisp. -
Избегайте избыточных скобок. В некоторых местах, где избыточные скобки особенно оскорбительны,
-
Вокруг условия в выражении
if(маркирует вас как нереконструированного программиста C) -
Вокруг приложения-функции, которое само является аргументом инфиксного оператора (приложение Function связывается более жестко, чем любой инфиксный оператор. Этот факт должен быть сжег в каждом мозгу Хаскеллера, во многом так же, как у нас, у динозавров, есть APL -to-left, в котором записано правило.)
-
-
Поместите пробелы вокруг инфиксных операторов. Поместите пробел после каждой запятой в литературе кортежа.
-
Предпочитайте пространство между функцией и ее аргументом, даже если аргумент заключен в скобки.
-
Используйте оператор
$разумно, чтобы сократить круглые скобки. Помните о тесной связи между$и infix.: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, у меня очень мягкое предпочтение использовать
camelCaseдля экспортированных идентификаторов иshort_nameс символами подчеркивания для локальных переменныхwhere-bound илиlet.
Ответ 2
Некоторые хорошие правила thumbs imho:
- Проконсультируйтесь с HLint, чтобы убедиться, что у вас нет избыточных брекетов, и что ваш код не является бессмысленным. /li >
- Избегайте воссоздания существующих функций библиотеки. Hoogle может помочь вам найти их.
- Часто существующие функции библиотеки более общие, чем то, что они собираются сделать. Например, если вы хотите
Maybe (Maybe a) -> Maybe a, тогдаjoinделает это между прочим.
- Часто существующие функции библиотеки более общие, чем то, что они собираются сделать. Например, если вы хотите
- Иногда именования и документация аргументов важны.
- Для такой функции, как
replicate :: Int -> a -> [a], довольно очевидно, что делает каждый из аргументов, только из их типов. - Для функции, которая принимает несколько аргументов одного и того же типа, например
isPrefixOf :: (Eq a) => [a] -> [a] -> Bool, важнее имя/документация аргументов.
- Для такой функции, как
- Если одна функция существует только для обслуживания другой функции и в противном случае не является полезной, и/или трудно думать о хорошем имени для нее, то она, вероятно, должна существовать в ней caller
where, а не в область модуля. - DRY
- При необходимости используйте шаблон-Haskell.
- Связи функций, таких как
zip3,zipWith3,zip4,zipWith4и т.д., очень меняются. ИспользуйтеApplicativeстиль сZipList. Вам, вероятно, никогда не нужны такие функции. - Производить экземпляры автоматически. Пакет derive может помочь вам получить экземпляры для классов типов, таких как
Functor(существует только один правильный способ сделать тип экземплярFunctor).
- Более общий код имеет несколько преимуществ:
- Это более полезно и многоразово.
- Он менее подвержен ошибкам, потому что есть больше ограничений.
- Например, если вы хотите запрограммировать
concat :: [[a]] -> [a]и обратите внимание, как это может быть более общим какjoin :: Monad m => m (m a) -> m a. При программированииjoinесть меньше места для ошибок, потому что при программированииconcatвы можете поменять списки по ошибке, а вjoinвы можете сделать очень мало.
- Например, если вы хотите запрограммировать
- При использовании одного и того же стека монадных трансформаторов во многих местах вашего кода создайте синоним типа. Это сделает типы более короткими, более краткими и более легкими для изменения в объеме.
- Остерегайтесь "ленивого ввода-вывода". Например,
readFileдействительно не читает содержимое файла в момент чтения файла. - Избегайте отступать так сильно, что я не могу найти код.
- Если ваш тип логически является экземпляром типа-класса, сделайте его экземпляром.
- Экземпляр может заменить другие функции интерфейса, которые вы, возможно, рассмотрели со знакомыми.
- Примечание. Если существует более одного логического экземпляра, создайте newtype-wrappers для экземпляров.
- Сделайте разные экземпляры согласованными. Было бы очень сложно/плохо, если список
Applicativeвел себя какZipList.
Ответ 3
Я бы предложил взглянуть на эту проверку стиля.
Ответ 4
-
Мне нравится пытаться организовать функции как бессмысленные композиции стиля, как как можно больше, делая вещи как:
func = boo . boppity . bippity . snd where boo = ... boppity = ... bippity = ... -
Мне нравится использовать ($) только во избежание вложенных парсеров или длинных выражений в скобках
-
... Я думал, что у меня есть еще кое-что во мне, о хорошо
Ответ 5
Я нашел хороший файл разметки, охватывающий почти все аспекты стиля кода хэскеля. Его можно использовать в качестве обмана. Вы можете найти его здесь: ссылка