Принципы, лучшие практики и шаблоны проектирования для функционального программирования
Существуют ли какие-либо известные принципы, передовые практики и шаблоны проектирования, которым можно следовать при написании кода на функциональном языке программирования?
7 ответов
Есть складки, разворачивания, карты и т. Д.
Я рекомендую использовать их как лучший опыт, так как их поведение довольно легко рассуждать, и они часто сообщают о цели функции (например, просто взгляните на знаменитую программу Evolution of a Haskell Programmer и сравните новичка со старшим, и с профессором).
Шаблон проектирования: пусть типы управляют вашим кодированием.
Выясните, какой тип вы пытаетесь вернуть.
Знайте, что определенные конструкторы типов поставляются с определенным синтаксисом, и используйте его для уменьшения желаемого типа. Вот два примера:
Если вы пытаетесь вернуть тип функции
T1 -> T2
писать всегда безопасно\ x -> ...
Теперь в теле вы пытаетесь создать значение типа
T2
, который является меньшим типом, плюс вы получили дополнительное значениеx
типаT1
, что может облегчить вашу работу.Если лямбда оказывается ненужной, вы всегда можете ее уменьшить.
Если вы пытаетесь создать пару типа
(T1, T2)
, вы всегда можете попытаться произвести значениеx
типаT1
и значениеy
типаT2
затем сформируйте пару(x, y)
, Опять же, вы уменьшили проблему до проблемы с более мелкими типами.
Как только типы станут такими маленькими, как вы можете их создать, посмотрите на типы всех переменных let-bound и lambda-bound в области видимости и посмотрите, как вы можете получить значение нужного вам типа. Обычно вы ожидаете использовать все аргументы для всех функций; если вы этого не сделаете, убедитесь, что вы можете объяснить, почему.
Во многих ситуациях, особенно при написании полиморфных функций, эта методика проектирования может сократить создание сложной функции до одного или двух вариантов. Типы управляют построением программы так, что существует очень мало способов написать функцию правильного типа - и обычно только один способ, который не является явно неправильным.
Лучшая практика: используйте алгебраические типы данных и воспользуйтесь преимуществами полной проверки из компилятора сопоставления с образцом. Особенно,
Никогда не совпадать с шаблоном подстановки
_
на высшем уровне.Установите параметры компилятора, чтобы отсутствующий регистр в сопоставлении с образцом был ошибкой, а не предупреждением.
Не следуй принципам, следуй за своим носом. Держите функции короткими. Ищите способы уменьшить сложность кода, что часто, но не обязательно, означает самый лаконичный код. Узнайте, как использовать встроенные функции высшего порядка.
Рефакторинг и уменьшение размера кода функции сразу после написания. Это экономит время, потому что завтра у вас уже не будет проблем и решения.
Шаблон проектирования: пусть компилятор выводит типы для ваших функций, и убедитесь, что эти типы в точности соответствуют вашим ожиданиям. Если типы являются более полиморфными или менее полиморфными, выясните почему.
Например, если вы пишете функцию сортировки в Haskell, ожидайте
Ord a => [a] -> [a]
Если ваш тип
Num a => [a] -> [a]
или же
[a] -> b
тогда что-то ужасно неправильно.
Рекомендация: после того, как вы подтвердите компилятором, что тип соответствует вашему, поместите явную сигнатуру типа для каждой функции верхнего уровня. (Или, если вы используете ML или Caml, напишите явный интерфейс.) Установите параметры компилятора, чтобы значения с отсутствующими сигнатурами вызывали ошибку.
Я бы ответил, возможно, немного расплывчатым принципом: старайтесь сделать ваш код красивым, как наиболее важный аспект. Процитирую Дэвида Гелернтера:
Красота важнее в компьютерных технологиях, чем где-либо еще, потому что программное обеспечение очень сложно. Красота - высшая защита от сложности.
и Брайан Керниган:
Управление сложностью - это сущность компьютерного программирования.
Если вы преследуете эту цель, это приведет вас к написанию кода, который легко читать и понимать (что очень важно), кода, который разбит на небольшие компактные части с четко определенной целью. Это поможет вам научиться наилучшим образом выражать свои мысли на конкретном языке.
(Все это не относится только к функциональным языкам, но написание красивого кода в них намного проще.)
Почему вопросы функционального программирования Джона Хьюза дают хорошую мотивацию для того, почему функции лени и высшего порядка (первого класса) предоставляют много того, чего не хватает в менее функциональных языках, и дополняют шаблонами проектирования.
В контексте Haskell я думал, что книга Real World Haskell содержит несколько полезных и практических советов по идиомам, абстракциям и классам типов и тому подобному. Typeclassopedia также всегда полезна. Основные, очень абстрактные классы типов можно рассматривать как шаблоны проектирования, за исключением того, что они применяются системой компилятора / типа и частью языка (если вы научитесь их использовать).
В контексте Lisp Пол Грэм написал книгу под названием On Lisp ( доступна онлайн), в которой он показывает, что функциональные языки идеальны для создания собственного языка программирования, а затем пишут свою программу на этом языке. Таким образом, встроенные доменные языки являются своего рода шаблоном проектирования.