Может ли кто-нибудь предоставить ссылку на хороший стандарт кодирования для 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
Я нашел хороший файл разметки, охватывающий почти все аспекты стиля кода хэскеля. Его можно использовать в качестве обмана. Вы можете найти его здесь: ссылка